Merge branch 'for-linus' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 Jan 2012 20:41:10 +0000 (12:41 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 Jan 2012 20:41:10 +0000 (12:41 -0800)
* 'for-linus' of git://git.kernel.dk/linux-block:
  cfq-iosched: fix use-after-free of cfqq

693 files changed:
Documentation/DocBook/media/constraints.png.b64 [new file with mode: 0644]
Documentation/DocBook/media/dvb/dvbproperty.xml
Documentation/DocBook/media/dvb/frontend.xml
Documentation/DocBook/media/selection.png.b64 [new file with mode: 0644]
Documentation/DocBook/media/v4l/biblio.xml
Documentation/DocBook/media/v4l/common.xml
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/dev-capture.xml
Documentation/DocBook/media/v4l/dev-codec.xml
Documentation/DocBook/media/v4l/dev-effect.xml
Documentation/DocBook/media/v4l/dev-event.xml
Documentation/DocBook/media/v4l/dev-osd.xml
Documentation/DocBook/media/v4l/dev-output.xml
Documentation/DocBook/media/v4l/dev-overlay.xml
Documentation/DocBook/media/v4l/dev-radio.xml
Documentation/DocBook/media/v4l/dev-raw-vbi.xml
Documentation/DocBook/media/v4l/dev-rds.xml
Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
Documentation/DocBook/media/v4l/dev-teletext.xml
Documentation/DocBook/media/v4l/driver.xml
Documentation/DocBook/media/v4l/func-close.xml
Documentation/DocBook/media/v4l/func-ioctl.xml
Documentation/DocBook/media/v4l/func-mmap.xml
Documentation/DocBook/media/v4l/func-munmap.xml
Documentation/DocBook/media/v4l/func-open.xml
Documentation/DocBook/media/v4l/func-poll.xml
Documentation/DocBook/media/v4l/func-read.xml
Documentation/DocBook/media/v4l/func-select.xml
Documentation/DocBook/media/v4l/func-write.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/libv4l.xml
Documentation/DocBook/media/v4l/pixfmt-grey.xml
Documentation/DocBook/media/v4l/pixfmt-m420.xml
Documentation/DocBook/media/v4l/pixfmt-nv12.xml
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml
Documentation/DocBook/media/v4l/pixfmt-nv16.xml
Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml
Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml
Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml
Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml
Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml
Documentation/DocBook/media/v4l/pixfmt-uyvy.xml
Documentation/DocBook/media/v4l/pixfmt-vyuy.xml
Documentation/DocBook/media/v4l/pixfmt-y16.xml
Documentation/DocBook/media/v4l/pixfmt-y41p.xml
Documentation/DocBook/media/v4l/pixfmt-yuv410.xml
Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml
Documentation/DocBook/media/v4l/pixfmt-yuv420.xml
Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml
Documentation/DocBook/media/v4l/pixfmt-yuyv.xml
Documentation/DocBook/media/v4l/pixfmt-yvyu.xml
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/selection-api.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml
Documentation/DocBook/media/v4l/vidioc-enuminput.xml
Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
Documentation/DocBook/media/v4l/vidioc-enumstd.xml
Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
Documentation/DocBook/media/v4l/vidioc-g-priority.xml
Documentation/DocBook/media/v4l/vidioc-g-selection.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/vidioc-g-std.xml
Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
Documentation/DocBook/media/v4l/vidioc-querybuf.xml
Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
Documentation/coccinelle.txt
Documentation/dvb/get_dvb_firmware
Documentation/feature-removal-schedule.txt
Documentation/hwmon/it87
Documentation/hwmon/lm63
Documentation/hwmon/sysfs-interface
Documentation/kbuild/makefiles.txt
Documentation/video4linux/CARDLIST.au0828
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.saa7164
Documentation/video4linux/gspca.txt
Documentation/video4linux/v4l2-framework.txt
MAINTAINERS
Makefile
arch/arm/boot/Makefile
arch/arm/include/asm/gpio.h
arch/arm/include/asm/memblock.h
arch/arm/kernel/head.S
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap-secure.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-w90x900/clksel.c
arch/arm/mach-w90x900/cpu.c
arch/arm/mach-w90x900/dev.c
arch/arm/mach-w90x900/mfp.c
arch/arm/mm/init.c
arch/arm/plat-omap/devices.c
arch/arm/plat-s3c24xx/cpu.c
arch/microblaze/boot/Makefile
arch/microblaze/kernel/setup.c
arch/openrisc/boot/Makefile
arch/powerpc/boot/Makefile
arch/um/Makefile
arch/x86/Makefile
arch/x86/ia32/Makefile
arch/x86/ia32/ia32entry.S
arch/x86/ia32/nosyscall.c [new file with mode: 0644]
arch/x86/ia32/syscall_ia32.c [new file with mode: 0644]
arch/x86/include/asm/Kbuild
arch/x86/include/asm/ia32_unistd.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/syscall.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/unistd_32.h [deleted file]
arch/x86/include/asm/unistd_64.h [deleted file]
arch/x86/kernel/Makefile
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/syscall_32.c [new file with mode: 0644]
arch/x86/kernel/syscall_64.c
arch/x86/kernel/syscall_table_32.S [deleted file]
arch/x86/syscalls/Makefile [new file with mode: 0644]
arch/x86/syscalls/syscall_32.tbl [new file with mode: 0644]
arch/x86/syscalls/syscall_64.tbl [new file with mode: 0644]
arch/x86/syscalls/syscallhdr.sh [new file with mode: 0644]
arch/x86/syscalls/syscalltbl.sh [new file with mode: 0644]
arch/x86/um/Makefile
arch/x86/um/sys_call_table_32.S [deleted file]
arch/x86/um/sys_call_table_32.c [new file with mode: 0644]
arch/x86/um/sys_call_table_64.c
arch/x86/um/user-offsets.c
drivers/base/power/domain.c
drivers/base/power/domain_governor.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/block/mtip32xx/Kconfig [new file with mode: 0644]
drivers/block/mtip32xx/Makefile [new file with mode: 0644]
drivers/block/mtip32xx/mtip32xx.c [new file with mode: 0644]
drivers/block/mtip32xx/mtip32xx.h [new file with mode: 0644]
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/char/random.c
drivers/hwmon/Kconfig
drivers/hwmon/adm1031.c
drivers/hwmon/coretemp.c
drivers/hwmon/it87.c
drivers/hwmon/lm63.c
drivers/hwmon/lm90.c
drivers/hwmon/max1111.c
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/Makefile
drivers/media/common/tuners/max2165.c
drivers/media/common/tuners/mc44s803.c
drivers/media/common/tuners/mt2060.c
drivers/media/common/tuners/mt2060_priv.h
drivers/media/common/tuners/mt2063.c [new file with mode: 0644]
drivers/media/common/tuners/mt2063.h [new file with mode: 0644]
drivers/media/common/tuners/mt2131.c
drivers/media/common/tuners/mt2131_priv.h
drivers/media/common/tuners/mt2266.c
drivers/media/common/tuners/mxl5005s.c
drivers/media/common/tuners/mxl5007t.c
drivers/media/common/tuners/qt1010.c
drivers/media/common/tuners/qt1010_priv.h
drivers/media/common/tuners/tda18212.c
drivers/media/common/tuners/tda18212.h
drivers/media/common/tuners/tda18218.c
drivers/media/common/tuners/tda18218_priv.h
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/tda18271-maps.c
drivers/media/common/tuners/tda18271-priv.h
drivers/media/common/tuners/tda18271.h
drivers/media/common/tuners/tda827x.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/xc4000.c
drivers/media/common/tuners/xc5000.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/ddbridge/ddbridge-core.c
drivers/media/dvb/dm1105/dm1105.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/af9005-fe.c
drivers/media/dvb/dvb-usb/af9005.c
drivers/media/dvb/dvb-usb/af9015.c
drivers/media/dvb/dvb-usb/af9015.h
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/anysee.h
drivers/media/dvb/dvb-usb/cinergyT2-fe.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u-fe.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dw2102.c
drivers/media/dvb/dvb-usb/friio-fe.c
drivers/media/dvb/dvb-usb/gp8psk-fe.c
drivers/media/dvb/dvb-usb/it913x.c
drivers/media/dvb/dvb-usb/lmedm04.c
drivers/media/dvb/dvb-usb/mxl111sf-demod.c
drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
drivers/media/dvb/dvb-usb/mxl111sf.c
drivers/media/dvb/dvb-usb/ttusb2.c
drivers/media/dvb/dvb-usb/vp702x-fe.c
drivers/media/dvb/dvb-usb/vp7045-fe.c
drivers/media/dvb/firewire/firedtv-avc.c
drivers/media/dvb/firewire/firedtv-dvb.c
drivers/media/dvb/firewire/firedtv-fe.c
drivers/media/dvb/firewire/firedtv.h
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/af9013.c
drivers/media/dvb/frontends/af9013.h
drivers/media/dvb/frontends/af9013_priv.h
drivers/media/dvb/frontends/atbm8830.c
drivers/media/dvb/frontends/au8522_dig.c
drivers/media/dvb/frontends/bcm3510.c
drivers/media/dvb/frontends/bsbe1.h
drivers/media/dvb/frontends/bsru6.h
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24113.c
drivers/media/dvb/frontends/cx24116.c
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cxd2820r.h
drivers/media/dvb/frontends/cxd2820r_c.c
drivers/media/dvb/frontends/cxd2820r_core.c
drivers/media/dvb/frontends/cxd2820r_priv.h
drivers/media/dvb/frontends/cxd2820r_t.c
drivers/media/dvb/frontends/cxd2820r_t2.c
drivers/media/dvb/frontends/dib0070.c
drivers/media/dvb/frontends/dib0090.c
drivers/media/dvb/frontends/dib0090.h
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mb_priv.h
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dib7000m.c
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib7000p.h
drivers/media/dvb/frontends/dib8000.c
drivers/media/dvb/frontends/dib8000.h
drivers/media/dvb/frontends/dib9000.c
drivers/media/dvb/frontends/dibx000_common.h
drivers/media/dvb/frontends/drxd.h
drivers/media/dvb/frontends/drxd_hard.c
drivers/media/dvb/frontends/drxk.h
drivers/media/dvb/frontends/drxk_hard.c
drivers/media/dvb/frontends/drxk_hard.h
drivers/media/dvb/frontends/ds3000.c
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/ec100.c
drivers/media/dvb/frontends/hd29l2.c [new file with mode: 0644]
drivers/media/dvb/frontends/hd29l2.h [new file with mode: 0644]
drivers/media/dvb/frontends/hd29l2_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/it913x-fe-priv.h
drivers/media/dvb/frontends/it913x-fe.c
drivers/media/dvb/frontends/it913x-fe.h
drivers/media/dvb/frontends/itd1000.c
drivers/media/dvb/frontends/ix2505v.c
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/lgdt3305.c
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgs8gl5.c
drivers/media/dvb/frontends/lgs8gxx.c
drivers/media/dvb/frontends/mb86a16.c
drivers/media/dvb/frontends/mb86a20s.c
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/nxt200x.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1411.c
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/s5h1432.c
drivers/media/dvb/frontends/s921.c
drivers/media/dvb/frontends/si21xx.c
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/stb0899_drv.c
drivers/media/dvb/frontends/stb6000.c
drivers/media/dvb/frontends/stb6100.c
drivers/media/dvb/frontends/stv0288.c
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0367.c
drivers/media/dvb/frontends/stv0900_core.c
drivers/media/dvb/frontends/stv090x.c
drivers/media/dvb/frontends/stv6110.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10023.c
drivers/media/dvb/frontends/tda10048.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda10071.c
drivers/media/dvb/frontends/tda10086.c
drivers/media/dvb/frontends/tda18271c2dd.c
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda826x.c
drivers/media/dvb/frontends/tdhd1.h
drivers/media/dvb/frontends/tua6100.c
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/frontends/zl10036.c
drivers/media/dvb/frontends/zl10039.c
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/mantis/mantis_vp1033.c
drivers/media/dvb/mantis/mantis_vp2033.c
drivers/media/dvb/mantis/mantis_vp2040.c
drivers/media/dvb/ngene/ngene-cards.c
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/pt1/va1j5jf8007s.c
drivers/media/dvb/pt1/va1j5jf8007t.c
drivers/media/dvb/siano/smsdvb.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/media-device.c
drivers/media/radio/Kconfig
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/tef6862.c
drivers/media/radio/wl128x/Kconfig
drivers/media/radio/wl128x/fmdrv_common.c
drivers/media/radio/wl128x/fmdrv_common.h
drivers/media/radio/wl128x/fmdrv_rx.c
drivers/media/radio/wl128x/fmdrv_rx.h
drivers/media/radio/wl128x/fmdrv_tx.c
drivers/media/radio/wl128x/fmdrv_tx.h
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/media/rc/Kconfig
drivers/media/rc/Makefile
drivers/media/rc/ir-nec-decoder.c
drivers/media/rc/ir-raw.c
drivers/media/rc/ir-rc6-decoder.c
drivers/media/rc/ir-sanyo-decoder.c [new file with mode: 0644]
drivers/media/rc/keymaps/rc-hauppauge.c
drivers/media/rc/keymaps/rc-videomate-m1f.c
drivers/media/rc/rc-core-priv.h
drivers/media/rc/rc-main.c
drivers/media/rc/redrat3.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/adv7170.c
drivers/media/video/as3645a.c [new file with mode: 0644]
drivers/media/video/atmel-isi.c
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-i2c.c
drivers/media/video/bt8xx/bt848.h
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-i2c.h
drivers/media/video/cx231xx/Kconfig
drivers/media/video/cx231xx/cx231xx-audio.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx231xx/cx231xx-core.c
drivers/media/video/cx231xx/cx231xx-dvb.c
drivers/media/video/cx231xx/cx231xx-input.c
drivers/media/video/cx231xx/cx231xx-vbi.c
drivers/media/video/cx231xx/cx231xx-video.c
drivers/media/video/cx231xx/cx231xx.h
drivers/media/video/cx23885/cx23885-417.c
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/cx25821/cx25821-alsa.c
drivers/media/video/cx25821/cx25821-audio-upstream.c
drivers/media/video/cx25821/cx25821-audio.h
drivers/media/video/cx25821/cx25821-cards.c
drivers/media/video/cx25821/cx25821-core.c
drivers/media/video/cx25821/cx25821-i2c.c
drivers/media/video/cx25821/cx25821-medusa-defines.h
drivers/media/video/cx25821/cx25821-medusa-reg.h
drivers/media/video/cx25821/cx25821-medusa-video.c
drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
drivers/media/video/cx25821/cx25821-video-upstream.c
drivers/media/video/cx25821/cx25821-video.c
drivers/media/video/cx25821/cx25821.h
drivers/media/video/cx25840/cx25840-audio.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-cards.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.h
drivers/media/video/davinci/dm355_ccdc.c
drivers/media/video/davinci/dm644x_ccdc.c
drivers/media/video/davinci/isif.c
drivers/media/video/davinci/vpbe.c
drivers/media/video/davinci/vpbe_display.c
drivers/media/video/davinci/vpbe_osd.c
drivers/media/video/davinci/vpbe_venc.c
drivers/media/video/davinci/vpfe_capture.c
drivers/media/video/davinci/vpif_capture.c
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
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/fsl-viu.c
drivers/media/video/gspca/Kconfig
drivers/media/video/gspca/Makefile
drivers/media/video/gspca/benq.c
drivers/media/video/gspca/gl860/gl860.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/jl2005bcd.c [new file with mode: 0644]
drivers/media/video/gspca/konica.c
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/nw80x.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/ov534_9.c
drivers/media/video/gspca/pac207.c
drivers/media/video/gspca/pac7302.c
drivers/media/video/gspca/se401.c
drivers/media/video/gspca/sn9c20x.c
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca561.c
drivers/media/video/gspca/stv06xx/stv06xx.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/topro.c
drivers/media/video/gspca/vicam.c
drivers/media/video/gspca/xirlink_cit.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/ivtv-i2c.h
drivers/media/video/m5mols/m5mols.h
drivers/media/video/m5mols/m5mols_capture.c
drivers/media/video/m5mols/m5mols_core.c
drivers/media/video/m5mols/m5mols_reg.h
drivers/media/video/marvell-ccic/mcam-core.c
drivers/media/video/marvell-ccic/mmp-driver.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9p031.c
drivers/media/video/mt9t001.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9v022.c
drivers/media/video/mt9v032.c
drivers/media/video/mx1_camera.c
drivers/media/video/mx2_camera.c
drivers/media/video/mx3_camera.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/omap/omap_voutdef.h
drivers/media/video/omap1_camera.c
drivers/media/video/omap24xxcam.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/ispccdc.h
drivers/media/video/omap3isp/ispccp2.c
drivers/media/video/omap3isp/ispccp2.h
drivers/media/video/omap3isp/ispcsi2.c
drivers/media/video/omap3isp/ispcsi2.h
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/omap3isp/isppreview.h
drivers/media/video/omap3isp/ispresizer.c
drivers/media/video/omap3isp/ispresizer.h
drivers/media/video/omap3isp/ispvideo.c
drivers/media/video/omap3isp/ispvideo.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-dec23.c
drivers/media/video/pwc/pwc-dec23.h
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-kiara.h
drivers/media/video/pwc/pwc-misc.c
drivers/media/video/pwc/pwc-timon.h
drivers/media/video/pwc/pwc-uncompress.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/pxa_camera.c
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-core.h
drivers/media/video/s5p-fimc/fimc-reg.c
drivers/media/video/s5p-fimc/mipi-csis.c
drivers/media/video/s5p-fimc/mipi-csis.h
drivers/media/video/s5p-fimc/regs-fimc.h
drivers/media/video/s5p-g2d/Makefile [new file with mode: 0644]
drivers/media/video/s5p-g2d/g2d-hw.c [new file with mode: 0644]
drivers/media/video/s5p-g2d/g2d-regs.h [new file with mode: 0644]
drivers/media/video/s5p-g2d/g2d.c [new file with mode: 0644]
drivers/media/video/s5p-g2d/g2d.h [new file with mode: 0644]
drivers/media/video/s5p-jpeg/Makefile [new file with mode: 0644]
drivers/media/video/s5p-jpeg/jpeg-core.c [new file with mode: 0644]
drivers/media/video/s5p-jpeg/jpeg-core.h [new file with mode: 0644]
drivers/media/video/s5p-jpeg/jpeg-hw.h [new file with mode: 0644]
drivers/media/video/s5p-jpeg/jpeg-regs.h [new file with mode: 0644]
drivers/media/video/s5p-mfc/s5p_mfc.c
drivers/media/video/s5p-tv/hdmi_drv.c
drivers/media/video/s5p-tv/mixer.h
drivers/media/video/s5p-tv/mixer_grp_layer.c
drivers/media/video/s5p-tv/mixer_video.c
drivers/media/video/s5p-tv/mixer_vp_layer.c
drivers/media/video/s5p-tv/sdo_drv.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-input.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa7164/saa7164-bus.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_mobile_csi2.c
drivers/media/video/soc_camera.c
drivers/media/video/soc_camera_platform.c
drivers/media/video/stk-webcam.c
drivers/media/video/timblogiw.c
drivers/media/video/tlg2300/pd-common.h
drivers/media/video/tlg2300/pd-dvb.c
drivers/media/video/tm6000/Kconfig
drivers/media/video/tm6000/tm6000-alsa.c
drivers/media/video/tm6000/tm6000-cards.c
drivers/media/video/tm6000/tm6000-core.c
drivers/media/video/tm6000/tm6000-dvb.c
drivers/media/video/tm6000/tm6000-i2c.c
drivers/media/video/tm6000/tm6000-input.c
drivers/media/video/tm6000/tm6000-regs.h
drivers/media/video/tm6000/tm6000-stds.c
drivers/media/video/tm6000/tm6000-video.c
drivers/media/video/tm6000/tm6000.h
drivers/media/video/tuner-core.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/uvc/Kconfig
drivers/media/video/uvc/Makefile
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_debugfs.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_isight.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/v4l2-subdev.c
drivers/media/video/via-camera.c
drivers/media/video/videobuf-dvb.c
drivers/media/video/videobuf2-core.c
drivers/media/video/videobuf2-dma-sg.c
drivers/media/video/videobuf2-memops.c
drivers/media/video/videobuf2-vmalloc.c
drivers/media/video/vino.c
drivers/staging/media/as102/Kconfig
drivers/staging/media/as102/Makefile
drivers/staging/media/as102/as102_drv.c
drivers/staging/media/as102/as102_drv.h
drivers/staging/media/as102/as102_fe.c
drivers/staging/media/as102/as102_fw.c
drivers/staging/media/as102/as102_fw.h
drivers/staging/media/as102/as102_usb_drv.c
drivers/staging/media/as102/as102_usb_drv.h
drivers/staging/media/as102/as10x_cmd.c
drivers/staging/media/as102/as10x_cmd.h
drivers/staging/media/as102/as10x_cmd_cfg.c
drivers/staging/media/as102/as10x_cmd_stream.c
drivers/staging/media/as102/as10x_handle.h
drivers/staging/media/as102/as10x_types.h
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/media/easycap/easycap.h
drivers/staging/media/easycap/easycap_ioctl.c
drivers/staging/media/easycap/easycap_low.c
drivers/staging/media/easycap/easycap_main.c
drivers/staging/media/easycap/easycap_settings.c
drivers/staging/media/easycap/easycap_sound.c
drivers/staging/media/go7007/go7007-usb.c
drivers/staging/media/lirc/lirc_imon.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/media/solo6x10/Makefile
drivers/staging/media/solo6x10/jpeg.h [deleted file]
drivers/staging/media/solo6x10/solo6x10-jpeg.h [new file with mode: 0644]
drivers/staging/media/solo6x10/v4l2-enc.c
drivers/usb/host/ehci-xilinx-of.c
drivers/xen/xen-balloon.c
fs/compat_ioctl.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/extents.c
fs/nfs/callback.h
fs/nfs/callback_xdr.c
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
include/linux/dvb/frontend.h
include/linux/dvb/version.h
include/linux/tty_driver.h
include/linux/videodev2.h
include/media/as3645a.h [new file with mode: 0644]
include/media/atmel-isi.h
include/media/cx25840.h
include/media/davinci/vpbe.h
include/media/davinci/vpbe_venc.h
include/media/media-entity.h
include/media/omap3isp.h
include/media/pwc-ioctl.h [deleted file]
include/media/rc-map.h
include/media/soc_camera.h
include/media/v4l2-ioctl.h
include/xen/interface/io/blkif.h
kernel/Makefile
kernel/capability.c
kernel/module.c
kernel/power/swap.c
scripts/Makefile.headersinst
scripts/Makefile.lib
scripts/checksyscalls.sh
scripts/coccicheck
scripts/coccinelle/api/devm_request_and_ioremap.cocci [new file with mode: 0644]
scripts/coccinelle/api/kstrdup.cocci
scripts/coccinelle/api/memdup.cocci
scripts/coccinelle/api/memdup_user.cocci
scripts/coccinelle/free/devm_free.cocci [new file with mode: 0644]
scripts/coccinelle/free/kfree.cocci
scripts/coccinelle/iterators/fen.cocci
scripts/coccinelle/iterators/itnull.cocci
scripts/coccinelle/locks/call_kern.cocci
scripts/coccinelle/locks/flags.cocci
scripts/coccinelle/locks/mini_lock.cocci
scripts/coccinelle/misc/doubleinit.cocci
scripts/coccinelle/null/eno.cocci
scripts/dtc/dtc.c
scripts/dtc/srcpos.c
scripts/dtc/srcpos.h
scripts/genksyms/Makefile
scripts/kconfig/Makefile
scripts/kconfig/confdata.c
scripts/kconfig/expr.h
scripts/kconfig/gconf.c
scripts/kconfig/lkc.h
scripts/kconfig/mconf.c
scripts/kconfig/merge_config.sh [new file with mode: 0644]
scripts/tags.sh
sound/core/Kconfig
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0.h
sound/pci/au88x0/au88x0_pcm.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_sigmatel.c
sound/pci/oxygen/xonar_wm87x6.c
sound/soc/nuc900/nuc900-ac97.c
tools/testing/ktest/compare-ktest-sample.pl
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf

diff --git a/Documentation/DocBook/media/constraints.png.b64 b/Documentation/DocBook/media/constraints.png.b64
new file mode 100644 (file)
index 0000000..125b4a9
--- /dev/null
@@ -0,0 +1,59 @@
+iVBORw0KGgoAAAANSUhEUgAAAlQAAAFYCAYAAACVsmLPAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
+/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sLCBIAKVtZsMAAAAxxSURBVHja
+7d3ZbqvIAkDRLsv//8v0QytXvpYZap7Wko56OAnE2AXbBSbhOI7jHwAAkr1sAgAAQQUAIKgAAAQV
+AICgAgBAUAEACCoAAEEFACCoAAAQVAAAzb2jvyMEWw0AmFvh37xnhgoAQFABAPT1zvruwtNlAADV
+VLxsyQwVAICgAgAQVAAAggoAQFABACCoYEohuFkugKACsmLq178DIKiAyJgSVQCCCigQU6IKQFAB
+BWJKVAEIKqBgKIkqAEEFFAgkUQUgqIACYSSqAAQViKkwxjIAEFSwbUyJKgBBBWJq8GUCIKhgm5gS
+VQCCCsSUqAIQVMBYoSOqAAQVLOk41lwXAIIKhoqqJyFUYhkACCpYMqpiQqjEMgAQVLBUVKWEUIll
+ACCoYImoygmhEssAQFDBElHVexkACCoAAEEFACCoAAAQVAAAggoAQFABAAgqAAAEFQCAoAIAEFQA
+AIIKAABBBQAgqAAABBUAgKACAOA/b5sAGjsO2wBgMWaoAAAEFQCAoAIAEFQAADtzUXohIQQbAYDi
+Dh9kmYIZKgAAQQUAIKgAAAQVAICgAgAgmU/5VeSTGQDE8InxeZmhAgAQVAAAggoAQFABAAgqAAAE
+FQCAoAIAEFQAAHtyY0/o4O7efe4JCzAXM1QAAIIKAEBQAQAIKgAAQQUAgKACABBUAACCCgBAUAEA
+IKgAAAQVAICgAgAQVAAACCoAAEEFACCoAAAEFVBICGMsAwBBBVPHVE4QlVgGAIIKpo6ps/9utQwA
+BBUsEVMpQVRiGQAIKlgqpmKCqMQyABBUsGRMzbouAAQVNHMca64LAEEFy0WVmAIQVCCqxBSAoAL6
+hI+YAhBUIKrEFICgAvqEkJgCEFQgqo4+3wuAoILto0pMAQgqICOQxBSAoAIyQklMAQgqICOYxBSA
+oAIyokpMAQgqICOqxBTAvN42AYwTVQDMyQwVAICgAgAQVAAAggoAQFABAJDMp/y4FIJtwJx8ehJo
+yQwVAICgAgDoyyk/HnMKhdE5RQ30YoYKAEBQAQAIKgAAQQUAIKgAABBUAACCCgBAUAEACCoAAAQV
+AICgAgAQVAAAggoAAEEFACCoAAAEFQCAoAIAQFABAAgqAABBBQAgqAAAEFQAAIIKAEBQAQAIKgAA
+BBUAgKACABBUAACCCgAAQQUAIKgAAAQVAICgAgBAUAEACCoAAEEFACCoAAAQVAAAggoAQFABAAgq
+AACGCKoQPAs2JQAIquwCUAI2JQAIqowCOPtvbEoAEFQRBaAEbEoAEFQFCkAJ2JQAIKgKFIASsClh
+szEKrDGoXkNuiOPwwim4iezYoc9+39iDfQbVq+mGEFOiCjZ7E23swR6D6tV8Q4gpUQWb7PeNPdhn
+UL26bAgxJapgk/2+sQd7DKr3EDE1y96mUPT1fqgh6Ffosbsz9mDdQfXquiEY/rUKlBtLYgoqDJZB
+Dmjlg8qRWlSBMSSmYLOoKhtUjtCiCowdMQUbRtXLswUgpkBU5XkXf9CmPJZ9nQJrft6Gife9XmC/
+t0mHg9tr3FcJYgrmjilgn8Fa55SfI7WYAvtnYKNBW+8+VLGn/zY6wtd4qDY1iCngx+BtdNCre1G6
+W3gPt7MXUwAwW1CJKjEFCzB2wODtH1SiSkyB/TKw+KB9DfnARJWYAvtnYKLB+m7+AJ+UgL2WTQmT
+jz1jEJVf0ASD7jXck2/vY1PCQscwE+6wfkz1CaqrB6wAbEoQVcBkMdUvqH49cAVgU4KoAiaMqb5B
+9bkBFIBNCaIKmDSm+geVArApYaOxZ4zCuoPq5VkDqL//F1Ow9qASVACV9/9iCtYfVIIKoOL+X0zB
+HoNKUAFU2v+LKdhnUAkqgAZvqoG1B5WgAgAQVAAAggoAQFABAAgqAAAEFQCAoAIAEFQAAIIKAABB
+BQAgqAAABBUAgKACAEBQAQAIKgAAQQUAIKgAABBUAACCCgBAUAEACCoAAAQVAICgAgAY3NsmIEYI
+//3zONK/7u/v/nx+zdPl/1rO0++LWd6vZZ59Xe7jSfnZSq3z6jnJ2ValX09PHj9AD2aoiPJ34Lo6
+wJWKiJQD7N2BN/WAzbNtZTsCuzJDRZeD8XHkH3zPZo5CSJudeTKbdrX+lkE7QkzFbq8VHj/AGTNU
+dDkY1ziw1jjY7nAA/wzKqxnIu5gSPICggoTIuDroXh1YRz3ohuCUlcgESOOUH81iZdR1fJ9+zL1Q
+use1Y6nrvLsearR46rHNAQQVw6l14HtyOurJz5USVqs9LynXt8V+ShBAUMHHQfdzFuMsQGqHSW5M
+PQmrVtdsjRCkOwY5gKBiGne3Okg5WJaMqbuw2uX5+P6aX4H8/f922F4AgorlgyD3hp47z3ycPfZf
+p/FSb00BIKjg4kD8/cm4mFNjKfd/OpsJyb2GJ+V+UzEXSK9wAfuvqGr9s7ooHRiV2yYgDCe8xUOp
+gHny2GNjVdwAOzJDRbUYSfnep8srfdCOWV6tr225ztzt3PpxiTRgdGaoAAAEFQBAX075sbS7C6dH
+OJU0w8/ocQEIKjY2w0F71bAQTMBOnPIDABBUAAB9OeXHY36tCAD8ZoYKAEBQAQD05ZQfl3xSCwDu
+maECABBUAACCCgBAUAEACCqgiRDczwtAUAFZMfXr3wEQVEBkTIkqAEEFFIgpUQUgqIACMSWqAAQV
+UDCURBWAoAIKBJKoAhBUQIEwElUAggrEVBhjGQAIKtg2pkQVgKACMTX4MgEQVLBNTIkqAEEFYkpU
+AQgqYKzQEVUAggqWdBxrrgsAQQVDRdWTECqxDAAEFSwZVTEhVGIZAAgqWCqqUkKoxDIAEFSwRFTl
+hFCJZQAgqGCJqOq9DAAEFQCAoAIAEFQAAAgqAABBBQAwibdNAECqcPKLJo8fH1cNN7+U8up7jpOP
+v6as//PvPr+/xPpTlsEazFABUDSmnsRTie/pvX74ZIYKgKz4+J55+fu7EMLPWZmU2auY9YsjejBD
+BUDRmDk7pdZq/Vf/P2bZT7/2OI7/rU/ICSoAiHIVLS2uFyq5Dtc3kcspPwCairmQvHUghhBOT1U+
+eQx/fyfQBBUALBNrtcPmc/l/QYagAoDqYi9ib/2zPZ2l+hVw7Ms1VAAkKXXbgpIXkH9eIF7r8T15
+bEJLUAHA4wD6FQ5PPoVXc/0ll3/3db/+sCen/ABIio7PU3U5YfIdY0++78n6RzPqxfiUYYYKqh94
+rv/AzFGV8nelouLue3JC5e5XzTx57E777SUcsa+4zxeIo8HlOw/vOgBwLBlqA1drGDNUAACCCgBA
+UAEATM2n/CpyQSIA7MEMFQCAoAIAEFQAAIIKAGBnLkovxI3XAGBfZqgAAAQVAEBfTvlBbXf3I3O6
+GGB6ZqgAAAQVAICgAgAQVAAAggoAAEEFACCoAAAEFQCAoAIAQFABAAgqAABBBQAgqAAAEFQAAIIK
+AEBQAQAIKiBFCGMsAwBBBVPHVE4QlVgGAM29bQIoGFOf/30c7ZcBrV/zd6/Rq6/7fs1/fs3T5Z+9
+AckZO2dvaL6XeffGJ/XxpPxspdZ59ZzkbKve278BM1RQOqaeDvbSy4CW/g5WV6/RUhHRcuwYc2W2
+VY3tP/hzY4YKar5bfLIDeLIMM1WsOnaOI/9AeTZzETt2YmbTrtbfMmhH2PfFbq/Syxxk/2iGCmrF
+1Kzrgplez78OpjUOsDu8qfkMyqsZyLvwSdleNZYpqGASLQe3GSpGHgNXB92r1+6or+sQvInptV+a
+eF/nlB/kDv7aO14xxUpahErqOr7Hc+yF9y3Hbul13l27NPJ+aJBTgYIKRo4qMcXK46b2wTVlHb9m
+3VpcXD/i85Kyb4v9lGCvZQoq2CiqxBQzvfY/ZzHOAqR2mOTG1JOwanXN1ghBunucR3INFYw4qMUU
+K/sLsO9rlXKuXSoZU99jcfXxmPpp5LP7f5W+B9Ukz4GggtGiSkxBn5ja/UL0v3D5/nO1jyq1zWos
+szGn/KDGTinnoliY9TV/FzZnr++U+z+dfcIw93qblPtNxVwUvcIF7N/7uZJRlbLMQS5KN0MFtQ4w
+YgrWGberjs+Y21vExmqN/eDAz0M4jsifrtZ5alh5ZyWmAMbaJxfe75qhgl7veMUUwDIEFfSMKjEF
+sAQXpUOrqJrk5nSwpLvT7yOMxxl+Ro9LUMFQUSWmoP348zN6XIIK7FgAWDWo/DZuAAAXpQMACCoA
+gM7iT/m5BgQA4P+YoQIAEFQAAIIKAEBQAQAIKgAABBUAgKACABBUAAB7+hfHbDX87cMFJQAAAABJ
+RU5ErkJggg==
index 3bc8a61efe301a4b32bd89862efd28219e9315c4..ffee1fbbc001ae316f40be9def3b2456e20c9118 100644 (file)
@@ -334,9 +334,10 @@ typedef enum fe_rolloff {
                <title>fe_delivery_system type</title>
                <para>Possible values: </para>
 <programlisting>
+
 typedef enum fe_delivery_system {
        SYS_UNDEFINED,
-       SYS_DVBC_ANNEX_AC,
+       SYS_DVBC_ANNEX_A,
        SYS_DVBC_ANNEX_B,
        SYS_DVBT,
        SYS_DSS,
@@ -353,6 +354,7 @@ typedef enum fe_delivery_system {
        SYS_DAB,
        SYS_DVBT2,
        SYS_TURBO,
+       SYS_DVBC_ANNEX_C,
 } fe_delivery_system_t;
 </programlisting>
                </section>
@@ -647,6 +649,18 @@ typedef enum fe_hierarchy {
                        many data types via a single multiplex. The API will soon support this
                        at which point this section will be expanded.</para>
        </section>
+       <section id="DTV_ENUM_DELSYS">
+               <title><constant>DTV_ENUM_DELSYS</constant></title>
+               <para>A Multi standard frontend needs to advertise the delivery systems provided.
+                       Applications need to enumerate the provided delivery systems, before using
+                       any other operation with the frontend. Prior to it's introduction,
+                       FE_GET_INFO was used to determine a frontend type. A frontend which
+                       provides more than a single delivery system, FE_GET_INFO doesn't help much.
+                       Applications which intends to use a multistandard frontend must enumerate
+                       the delivery systems associated with it, rather than trying to use
+                       FE_GET_INFO. In the case of a legacy frontend, the result is just the same
+                       as with FE_GET_INFO, but in a more structured format </para>
+       </section>
 </section>
        <section id="frontend-property-terrestrial-systems">
        <title>Properties used on terrestrial delivery systems</title>
@@ -767,7 +781,8 @@ typedef enum fe_hierarchy {
        <title>Properties used on cable delivery systems</title>
        <section id="dvbc-params">
                <title>DVB-C delivery system</title>
-               <para>The DVB-C Annex-A/C is the widely used cable standard. Transmission uses QAM modulation.</para>
+               <para>The DVB-C Annex-A is the widely used cable standard. Transmission uses QAM modulation.</para>
+               <para>The DVB-C Annex-C is optimized for 6MHz, and is used in Japan. It supports a subset of the Annex A modulation types, and a roll-off of 0.13, instead of 0.15</para>
                <para>The following parameters are valid for DVB-C Annex A/C:</para>
                <itemizedlist mark='opencircle'>
                        <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
index 61407eaba020342b40d6ba8d5588d4c30e07beb9..aeaed59d0f1f5d3d9baeff4af53eb803a7b50355 100644 (file)
@@ -45,8 +45,8 @@ transmission. The fontend types are given by fe_type_t type, defined as:</para>
   </row>
   <row>
      <entry id="FE_QAM"><constant>FE_QAM</constant></entry>
-     <entry>For DVB-C annex A/C standard</entry>
-     <entry><constant>SYS_DVBC_ANNEX_AC</constant></entry>
+     <entry>For DVB-C annex A standard</entry>
+     <entry><constant>SYS_DVBC_ANNEX_A</constant></entry>
   </row>
   <row>
      <entry id="FE_OFDM"><constant>FE_OFDM</constant></entry>
@@ -63,6 +63,10 @@ transmission. The fontend types are given by fe_type_t type, defined as:</para>
 <para>Newer formats like DVB-S2, ISDB-T, ISDB-S and DVB-T2 are not described at the above, as they're
 supported via the new <link linkend="FE_GET_SET_PROPERTY">FE_GET_PROPERTY/FE_GET_SET_PROPERTY</link> ioctl's, using the <link linkend="DTV-DELIVERY-SYSTEM">DTV_DELIVERY_SYSTEM</link> parameter.
 </para>
+
+<para>The usage of this field is deprecated, as it doesn't report all supported standards, and
+will provide an incomplete information for frontends that support multiple delivery systems.
+Please use <link linkend="DTV_ENUM_DELSYS">DTV_ENUM_DELSYS</link> instead.</para>
 </section>
 
 <section id="fe-caps-t">
diff --git a/Documentation/DocBook/media/selection.png.b64 b/Documentation/DocBook/media/selection.png.b64
new file mode 100644 (file)
index 0000000..4161865
--- /dev/null
@@ -0,0 +1,206 @@
+iVBORw0KGgoAAAANSUhEUgAABIsAAAHpCAYAAAACi7yYAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
+/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sLCBAiCLMGMtAAACAASURBVHja
+7d3rkds4FgZQaMohTBY7ObRCV+fgyWJy4P6wJavVIgmSAIjHOVWu3bElPkBSAj5dgpdpmqYAAAAA
+ACGEvzQBAAAAAHfCIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMDDD00A
+21wul9XXTNN0aHnP749Z39o2rK0jRzssLX/pvVve9+61S69Jdey2bn/sMTx6TAAA/cIW+oVb+2tb
+3p+izwioLIJsHYe9X+a979vae89ut6Pb1+txBwD0C3vZN0ERrFNZBAct/ZJxuVx2Vdg8v+/oLyEx
+69j7xbq2/1u2e0u75Th2Mevf8ytVzDkDAOgXjtYv3LquVP0nQRHEUVkEBTsJve/r0hfu2hdz7e0W
+27HQ4QAA9Avr7BcJiiCesAhO+GKK/YIt8SV+RscoNmippUPl1jIAQL/w3PUc7Y8JimAbYRGc9KVY
+Yu6b3OsYNUTRuQAA9AvL9AtT9LsERbCdOYsAX74ZOiVbO1M6LQCAfmH7/TzohcoiqOhLK+eXV4p1
+xP4y1krF0X1bn7dXBwIA0C+ss19oagAoR1gEJ4j9osv5iPq965imKUk59eidwNc/AIB+oX7h/HpK
+tzeMzm1oQJIv7Ra/eO/7sOWxtgAAtN0v1N+DdcIiyPQFlPP1JbZpTyehl19q1joQOhgAgH7hOf3C
+Pct9tz36c7DMbWhQwPMXUYkOQ6517P3Sj/216axJEdfWoyMBAOgXpukX5uqv7Xm/W9JgnsoiSGxr
+4FHiiyvlOu7v21pu/PqLzuuvOTHtlmIZW/bz+f1r6177ewBAv1C/8FwqjCCesAgSdwK2dAh63e+5
+fX8XuBxtt1SdkZhy6djt37vNOioAoF84Sr8wV39tzzIERvCd29Agg7knQ8T+unTk15mc64j5El17
+KsbRW75inrqR6glj79rELWsAgH5hmn7hmcckpt8HI7tMRjYAAAAA/KayCAAAAIAHYREAAAAAD8Ii
+AAAAAB6ERQAAAAA8CIsAAAAAeBAWAQAAAPAgLAIAAADgQVgEAAAAwIOwCAAAAIAHYREAAAAADz80
+AQAAqVwuF40AABWbpmn1NbvDIh0BAKDGzg3n0T8EgD7sCot0BAAAmDNNUwj6iwBQlS3fzIduQ7vd
+blobAMjuer1qhKZ6o4IiAGiZOYsAAMji0w+LAHC6jx0/unkaGgAAAAAPwiIAAAAAHoRFAAAAADwI
+iwAAAAB4EBYBAAAA8OBpaAAAFDf3ZJa5J6htef3za5eeyDb3urWnxsQuM/V7jmxX7Dr3HIMUbfj6
++qXjurZ977Zja1vuaVOAnqgsAgCgqKWB+rt/2/r6s7Z/z3aesf0x+1fjdgFQjsoiALpyfRng3J5+
+Fb7/2+3NL8Xv/m1pWa/veX7t/XXXN4OtuWXs+fe59c/t45H2erd/Mdu/9XX0b63q5zWkWHr9/d8+
+rtfFapOY9byz9L7X5e7ZzqVKmT2VP3ts2cc966+1MmfuGKkkAvhFZREA3XgON94FNnMhzlJQNLes
+1/ffX/f62ue/fw1d3r3m9d/nlhu7/rX22rv8LW20d/voT8ztYbEBzNJrS4YMubbzzNCidLs+BzX3
+datsAjiXsAiALrwLfPYGE1uXtaVK5l2YNLes2OXurdI5svwtbaSKiFdbg5Cl18f821y1UupAZu92
+1njblwobgLG5DQ0AZqSofjkSnOSuvsmxf2fsB5SUMtT5vN2+LC82xNoziXaJNthyO11MBdHS7YUA
+5CUsAmAo91u97rdGLc1jdKQi5t08QiH8uSVrTcwcSkekWv7avuTeD1hzD2TuwcOWqqIS8wa9C01G
+nD/neV9fQzQAyhMWAUAma5NVA23KEeLMhUZHJ5g+e/9jXyscAqiLOYsA6MK7+XLW5gWK/fdnsYHP
+2uvWJtveu969ti5/bxsJzNgTDOx5JP2z1yAmNsC4T7j8+ifXdj6vs7VjlGsdQiSAc6gsAqAbz7eY
+Pf9dqmVtWd7cbWivE0LPbe/rv80tL1Vb7Vl+TBvl3g/a8nx70dIj7e9/v/b6mKer1bBfc9tZ65w8
+pdt1bh1zQdFaGwNw3GWapmnzmy6XQx1wAIAt7gHTjm4LJTuWv/uI084QYC482Pv6LfMSvXtc/Nag
+pNR+xb7+yLYeXX9MG669ZunYpN7mEeeJAsZx/4y7/P7vmP6U29AAAChq6yPm9z6S3n7t34/c648J
+Z97N49TKuQDQOpVFAED1VBY10rGMrCwCAMpRWQQAAADAIcIiAAAAAB48DQ0AADqSciJsAMYkLAIA
+gI4IgwA4SlgEAADAZh9/X9/+/ed/t8Ovf37t3PKWXje3rq3LTP2eI9sVs961969t59r2LbX16zJi
+t+Xzv1vyduE4YVHpD9SZsuDnX4COlA7HLD/Ferase2lZW7Zh6/a+vn6pDda27912rK0vVbsCAEB1
+45qFwf3H39dNIcm715fY/rWQKsV7Wj5me93Dn6VlxgZKnEdYVPLiXAgTPq7X6BBh7rWpln/kPWv7
+LigBAIDGxzUrVT+vocTS6+//thYs7A1plt73utw927kUeixt3xnhWEybzO13qe0VHtVDWFTq4nwK
+cmKDni2B0NLy7/82F/4srWdPYLRneVvWUWvgNNfuAjIAALoZ10TcHhYbwNz/LiYwStpvf3PbU47t
+zL0v727/WqvqijlmEEIIf2mCAh+oK0HR0UBhbflbbuVKsT1ry4vdhhRt/nm7PdZdYr0AADCCreHC
+0utj/m0u3EkdcuzdzntQ09MxS7Gud23iFrQ2qCwqeXFmrjBZWv7n7XZ6WFLDNgAAAGNLGeq8Vilt
+ndz53fKO7sMZc0DlPjaCpfKERTVfKBsmqy617hr2de21qeduAgAAzvM6YfKWypQS8wa9q6IpVT3z
+vPyYp4pBLGERu55i1sSXytO2q2oCAAAe44MMIc5caDQ3B1KSsVzF4dC7p6KthWgqiOohLKr5A2zj
+RNW511/LurY8NQ4AAEhv661OMY9RXxwDPAUP9/+OGjtsDB+ObufzOnMFOTHLnZvoWhhDLBNcl/xA
+PRherIUka7dfLS333Z/a9j/VOoRIAACwc0wy86SzL/3tmadvLU12/Pra2vZryz6V3OZ3f44eMwhB
+ZVGZi/jpFqi5qqAj1UJry495Gltupbdhbh1zQdFauwEAAL/72i+PkU/x+hoeRb93O/fMi1R6Iuet
+xyz1emNDQRNc10NYVOoieQl0jnoNN2KWXyoo2jMH0lnbfKTdzm5nAAA4bXyzMJnyXHVLC0FA7fsV
+cxveu7mCWjoG1EFYVPKDZ2GS5diAYW0ZtQYYJZ/gtrSuexs9h201txsAAFQ7vtkYMGx5/dHXHgk/
+atmvI+9PNYF0ioqvGqrG2O4yTdO0+U2XSwghhJuBNABQwPV3qL+j20LJjuXvPuL9KPnRBWCbtVvE
+hCrsOq9+96Muv/87pj+lsggAAKDFAeBLsCBIaJ9jSC2ERQAAAB0QHgGpCIuI++JZmZRbmTkAAFTW
+h98QHn1cPzQYFPR5+6x6+4RFRJ7IN40AAAA19dGfwp+Yx6HHPr4cQFgEAADQuNfwZy08inkEOzAu
+YREAAECjYiqKdvl50bg04Ujg+Xr7Ze5bw1q63VNYlPzgXzUCAP13zNyeDJB/bJErCAKKB0WtERYB
+AACcNWA9IRBy6xnDX3eColXCoowUbgLQk0kTAMQPRguFQItPOHuzDXuCoss/jieV9Ul+Hrg2TwqK
+WnvioLAIAABgy6CvgiBoz/apKGL4a1dQFE1YBAAA8DywK3hrWOoAJ1U1EXR3XQuKNhEWAQAAYwwW
+Gw6B9u6foAgERXsIiwAAgLYHgoUnia4tgBESwcL1UUlQ9Hn7bCo8EhYBAAB1DvJOenR860GLoAh+
+f4ZUFBS1RlgEAACUH8R5ZLx9hJyfMYKiQ4RFAABAuoGSEMj+w9mfQ4Kiw4RFAADA+iBICAS08Fkl
+KEpCWAQAACMPrMwLBPTyeSYoSkZYBAAAPQ6ahEDASJ95gqKkhEUAANDaoMgtYQB/PhMFRckJiwAA
+oJYBjxAIYNvnpqAoC2ERAADkHlQIgQDyf+4JipIRFgEAwN4Bg3mBAKogKEpLWAQAAK+DASEQQDME
+RekJiwAAGIpbwgD6ISjKQ1gEAEAXhEAAZPl+GSwoCkFYBABA7Z10IRAAZ30HDRgUhSAsAgDgrA64
+eYEAqPl7atCgKARhEQAAR/17CSGEMP186WSHa9HNEAIB70zTNMy+Xi4XBzyRkYOiEIRFAAAs+ff8
+gYcQCICSRg+KQhAWAQCMSQgE0J25KioVR/EERb8IiwAAenJGCPS/6ctgZHp0sG+OB0AFXkMk4dF7
+gqI/hEUAAC04qxLof5O2B6B7gqKvhEUAAGcSAgFQ2HOlkSojQdE7wiIAgFxOvCUMAFgnKHpPWAQA
+sJUQCIBOjFxlJCiaJywCALgTAgHAEARFy4RFAED/zAsEAKvuVUa9VxgJitYJi6DmD+uf7//+8s/6
+a969ds/yU6xn636uLWttu9e2dakdX5cRuy2Xf/K2ETBDCAQAbHBWUPS63toJi6BSS8HD9DM+eJh7
+barlH3nPme2y5h7+LC0zNlACdnaq/r5+v/Zzh0NCIADotsJIUBRPWAQ1fjg/BSKxQc+WQGhp+fd/
+mwtJltaTOzCKbZe5fSoV6giPYKXD9BQCFSMEAoCx+x+Cok2ERVCZtUBk6e9TLP/5dqrY8CfmFqy1
+7Xm+/evdenO3C5CgMyQEAoC+xibT1EV1kaBoO2ERVCp38LG0/CPhT+vt8q4dlsIrARVDdBTffB58
+hGv29X7+d3v8/+v1+ui0AgDEqiUo+rx9NhUeCYug48FcCOfPI7T3faXmQOrtWECJa/eo5xAIAKi8
+v9Dw/EU1BUWtERYByQaXe8OQ5/fVXNUEvVyruQiBAIBaCIqOERZBJ7ZOVJ17/bUParfs1+utaGu3
+oKkgIqczrpfHuf+l43NzMABgpD5IQ/MXCYqOExZBxQPCI6HDWoVOzCPhlwaNJQa8c3MFCWPo9Zov
+zbUEAPRGUJSGsAgqE/M0siOBydryY546VmKw+jpwzt0ukMtZlXOuBQAgeb+m8uoiQVE6wiKo0Gsw
+kmKwOjcvUEuTMadul63rjQ3STHA9SGdJCAQAUA1BUVrCIqjU0m1ksYPFtWWcFWrEPHZ+7rH1Z243
+43BLGADATD+pwuoiQVF6wiKoWMzgce01a4HMGQPZLWFXim3J3Y4G+w11boRAAABdERTlISwCoHlC
+IACAgn2v6dczUmurMBIUpSMsAqDejoh5gQAAiCAoSktYBBQf4BuIIwQCACAVQVF6wiLAgJyk3BIG
+AEApgqI8hEUARBECAQDwpX9Y4ZPRchgtKApBWATgS14IBAAAb40YFIUgLALolnmBAADI3ufsuLpo
+1KAoBGERQHtfyEIgAADIauSgKARhEUBV3BIGAEBzfdjOqotGD4pCEBYBlPkCFQIBAED1BEW/CIsA
+DhACAQCMpbYKmmmaqtmO1quLBEV/CIsA3n3ZmRcIAACGISj6SlgEDEUIBABAT16reWqpNGqJoOg7
+YRHQDbeEAQAAWwiK3hMWAdUTAgEAQGQ/9qnSqHSVUWvzFgmK5gmLgNMIgQAAgDMIipYJi4DkzAsE
+AADnu1f5mMfoK0HROmEREE0IBAAAtOysoOh1vbUTFgEhBLeEAQBAr0pWGNU8b5GgKJ6wCDonBAIA
+AEYnKNpGWASNEgIBAACb+vODzmEkKNpOWASVMS8QAABAGrUERZ+3z6bCI2ERFCIEAgAAanC5XLJW
+F9Uyb1FNQVFrhEWQ+oOxUCgkBAIAAHaPJzIHRmcTFB0jLILaPrSFQAAAALsJio4TFkEhQiAAAKCq
+MUqH1UWCojSERZD6A1coBAAAUJygKJ2/nE4AAABASqUrlgRFaaksghQfhD+1Af1QHQcAQEsERemp
+LAIAAIBB1fCI+yMERXkIiwAAAIDmCYrScRsaJOYWHlrkVkoAgIHHMB08FU1QlJbKIgAAAKBZgqL0
+hEUAAABAkwRFeQiLAAAAAGaMFhSFICwCAAAAeGvEoCgEYREAAADAN6MGRSEIiwAAAGB4l8sl+TJb
+fsLayEFRCCH8cEkAQJkOTo5OGAAAaY0eFIUgLAJgcCV/8VpalyAJAOB8gqJfhEUADKPmUuh32yZA
+AgAoR1D0h7CIrgduBlp9DqqdM4xyHj9vv3MTACAfQdFXwiKAmcH5K4P19o9hT/vlfAQASENQ9J2w
+iO4HjQZUGKyPeXxG2V/nIQCQyuVyGa5PJSh6T1iEgR0kOIcN2H2OOA8BANoiKJonLAIwYG+6vfne
+Ls5BAIBlgqJlf2kCeh/oGVRyxvntvNO22gkAoE6ConUqiwAyDthDUOWRsi1xDgIAHHFWUPS63tqp
+LAIoMGAXdhxrP5yDAABHCYriCYsYYuBnkIQBu/ZCmwIA4xIUbSMsAjhhwI42Ort9tTEAMApB0XbC
+IoYZABoY4Vpoo120jfMQACCVWoKi1ibRFhYBGKhrD+0OANAdQdF+wiKAkwfqBusCCwAA0hIUHSMs
+YqjBoAEp1Pe54LoEACAlQdFxP5xGAOebpilcLpfh9rkVKY6NUAwAID9BURrCIoBKjBQY1Rqc5Gz/
+uWULkQAA0hAUpSMsYriB4YgVHLR1rfR+ftb0eVBDW79ug/AIAGA7QVFawiJgqIH5O7UNznsOjGpo
+69rb9nn7BEcAAOsERekJixhuIN77YJxjg3OD9D4/C1q93gVHAADLBEV5CIsAKhyk9xZonhV09NSG
+giMAgGWConSERQCRg3QD9PaOmXMSAGAMgqJkHc0Qpin85ZQip5oHMgZZ7BmglwwhejlHS+/HSLeY
+lj4nAQBqJChK2nkPIQRhEW0NisAAvbXvmslxse8AgDFcNoKiPIRFGMhCxV9+LZ+jpYMitAMAQA6j
+BUUhCItoZKB4HwAZCGFwPt71v9b+joE2AQDa6sO1ZMSgKARhEUCSwTnaXfsAAPRl1KAoBGERmbSU
+SEvPcY62t72CkPh20lYAANuNHBSFICyikcGOQSKtnaejEhQ5PwEAWjd6UBSCsAjAgFwbD9N22g8A
+YJmg6BdhEcnlmNi6pW0G134egg7tCACQk6DoD2ERBjuAa157AgAMTVD0lbCIpFqu0FFdRM2D8NrP
+z5zbJ9jQrgBAe/25lvoagqLvhEU0O5Ax0IE+OxbU8zkLANA7QdF7wiIAqiXM0MYAALkIiuYJi0im
+xYmtc+4DBt+ue+0IAECdBEXLhEUYlAMAAAxstB/NBUXrhEUAVNepEAQDAJDDWUHR63prJyyiukHj
+1kFi6kGlW9HgXIIiAAD9uRwERfGERQAAAEDXBEXbCIs4rMdKHNVFcM41oqoIAMDYJzVB0XbCIqqy
+d6BogAkAAMCrWoKi1ibRFhYBsImqIgAA/boW+nSCov2ERVTz4VLbQNGtaAAAAG0SFB0jLKIbqhLA
+9QsAQJyefxwXFB0nLIJBP0BpSy1himsCAICaCYrSEBZRxaAx1UBYdQK9XRsAANBKf/Xs8ZigKB1h
+EQCnEvICAHCUoCgtYRG79Dyxdc59Bdc9AABn9ud67NMJitITFtEdVQoAAABjEBTl8cOpBZBOjl9q
+eg5AhbsAAG32UWvs1wmK0lFZxKkfNLk+UFIv1+03AAAA9RIUpaWyCCCRnkNFgSkAgD7cnLOrigRF
+6akswoDRvlMxt2kBAMA8QVEeKovodhB8uVwEPBTjXKvvMwAAQL9Uny6F0YKiEFQWAVT7hSxMAQCA
+c40YFIWgsoiTBsSlBsGpq4umaTKAJ9t1AQAALfVHex8bjRoUhaCyCKDKL+aavngFYgAAjGbkoCgE
+lUUAmwlPjlOhBwDoC+rP1Wr0oCgElUWc8IFY+kMl9fp8OYx9HZQ4/oIUAAA4h6DoF5VFACtKBoSC
+IgAAatdrn1VQ9IewiKID5V4+VEx07bz3pQsAAP0QFH0lLGIIqZ+KRl9qODcERQAAtDK26o2g6Dth
+EVCMwG6cL1wAAGiBoOg9E1xTbHB/9oDYRNfUSFAEAEAr/dbe+q6ConnCIoATv3BrJxQFAKBHgqJl
+bkMDKGz0aiLVVAAA+m5nEhStU1nErB6fguZWNM4+/wQlAABwnrOCotf11k5lEUBmAiIAAPRjzyco
+iqeyiLd6rCrKtT2qi5g7z1QSAQBAHQRF26gsAjhIIAQAgL5tvQRF26ksAjhomqYvfwAAgDrUEhS1
+Nom2yiLeDnxTqTWVvlwuBvUUuYZUHQEAUKve+6qCov2ERQAZCY4AAGihr9pbf1VQdIzb0Fj8sDjC
+wBi+X18q2gAAIC9B0XHCIoYlzOIsQiMAAGrup7bcVxUUpSEsAjjxyxgAAEhDUJSOsIgsA9dWqnZU
+F1HDdSc0AgBAP/UYQVFawiKASr6MAQCA7QRF6QmLACohMAIAoMY+as39VEFRHj+c+qQepLZ2a9fl
+ckm6/9M0ub2t4XPj7C9C5w8AAOwjKEpHWATw5F1QUzpAEhgBAFCbe5+41n6qoCgtt6ExdFVRru12
+O1FfLpfL40+L1yUAAPRMUJSesAhgg5LBkcAIAIDa1NZHFRTlISwC2KlEaCQwAgCAc40WFIUgLBqe
+W9Dybb9B/jgERgAAjDaOHKWPOmJQFIKwCCCJ0nMaAQAAeY0aFIUgLCLhQBnIdy2oLgIAoDY991FH
+DopCEBa5sMk60NfGzqPWz6cc++K6AACgZqMHRSEIiwCyUG0HAMAIevshUFD0i7DIBW1QnHl/VFHg
+fAIAgPoJiv744XQAyONyuQh3AIDmTdOkavqlj1fzsXKO7CMo+kplEUBjnQkBFAAApCMo+k5YNCC3
+oJXfL4N7AACgxDjm+U+r48ySBEXvCYsACnxp+zIGAIC6CIrmCYsGo6rovP0zuAfXAwD47qb0mKZk
+lVFL54mgaJkJrvGFAax2MlzvAAD0QlC0TmURQAGeIAIAwNn90RJVRrX/yHhWUPS63toJiwaiMsAx
+wPkEAACjEhTFExYBcAphFwDAOXJXGNXYzxMUbSMsAgAAALolKNpOWDQIv+A7Fpyv5XmLzLkEAOjH
+6p+2eL7UEhS1Nom2sAgAAADojqBoP2HRAPwC4JjgXLL9AAC8U+IJaWcQFB0jLAIAAAC6ISg6TlgE
+QBTzFgEA6OttcUYVuaAoDWFR59zi4diAawEAgBEIitIRFgEAABDFjzx9a7m6SFCUlrAIgFM7EAAA
+cISgKD1hUcek/o4RuBYAANiitR8HBUV5CIsAAACA5gmK0hEWdcqv9I4V5JLr1ybXAgDov+Kc2UtQ
+lJawCAAAAGiWoCi9H04rYpjU9iu/puAz4ZLlOpimyecNAECnfb0cBEV5qCzqkCDDMcNxBgAA0hgt
+KApBWEQEv/IDJQnVAACMA2sxYlAUgrDIIItqPjgdO1wHrgcAMO6AeowaFIUgLAJoml98AAAgvZGD
+ohCERRiIahuK6PXXN9VFAAD01rcbPSgKQVjk4sMxBNeENgYAIIQgKLoTFjFL5Qzgs6JvgiIAfI/A
+H4KiP4RFYJCMjpT2064AAEMTFH0lLNLpx7GkUTWFlbm3xXWhPQEAchEUfScsovpBKBiU+9wYrS21
+IwBAGYKi94RFOv5UOEB2TF2baNMcbaf9AICzxzo1ERTNExYB+OJuarsEHtoMAOAoQdEyYRHNDELB
+4NxniPbVVgD4nsH5cpSgaJ2wyMWGY4tjp507bR9tBADw1VlB0et6aycsAkg8QM+theq/UtsoENEm
+AACxBEXxhEU0NwgFA3SfJ+/aH+0AADBHULSNsMigAMeYho5Ta4Fu6cBo1GtGWAkAME9QtJ2wiGYH
+oWCA7rNl7rg4BwEACKGeoKi1SbSFRQ0PEHCsOW9wfsZxEehuP072DwD0Vxm3Dyoo2u+HUx+g/g5Q
+60HR5XI5pR3v6+whaNMRBwCIJyg6RlhENwMpMCCv/3PmrPZ9Xm9rn3fOSQCAbQRFxwmLDGZpYEA8
+TZPKiMHPKddHnvOwxrZ1nQAA7CcoSkNYBFCxHqv+agiM7l6344z2Fg4B0INeftyk7XNFUJSOsAgf
+6uDaPGXfagxJ5rYpxbEQCgEA5CMoSktY1BiDjXEHwn6tGe8ccp347AUAYJ2gKL2/nFYGpIDr8sx9
+9TkEAMBegqI8hEUN8cu2Ab9zwHljv9H2AADvCYrSERYBGLTbf20OANA0QVFa5iwySABci1W1hQo6
+5xwAwBaCovRUFjXC4MmAzLngHBmpTbSLcw4AIIagKA+VRQAG7FW3kYDUOQcAcKbRgqIQVBY1IcdA
+yaDBOcF5A3bXn88r5xwAQBtGDIpCUFkERQZqwh0M1tO0n2vJOQcAUMqoQVEIwiIAA/YG21No5JwD
+AMhp5KAoBLehVc8taAZvJc8N0h1vt/6UaWO0CQB9j13gDKMHRSGoLAJINlDn3HYfsYPqvAMASEtQ
+9IuwyMACcB11dVxGCI2cgwAA6QmK/hAWVUwZZ3+Du9THdJomg0aDcRaOXS+fo85HAIC8BEVfCYsM
+DnBMnX8Mc821FB65BgFokR8zaZGg6DthEaT+gvypDaBW7zqvNQRIOtUAAOcQFL0nLAJgaEtBTcog
+SSAEAFAXQdE8YREAzBDwAAD0SVC0TFgEKQaU//z637lb0O7/DgAAwLkEReuERVBAzDxGAiUAAIC8
+zgqKXtdbO2ERVGItUBImAQDQRL/WE9G6O569EBTFExZBQnOBToonpKlOAgAA2EdQtI2wCAqICXEE
+SgAAAOkJirYTFkEl1kKcFGFS7HIESgAAHOpzuhWNStQSFH3ePpsKj4RF0IhS1UkxyxEmAQAAtasp
+KGqNsAg64nY3AACg6jFLoYozQdExwiIY7cPZ7W4AAEDHBEXHCYuAL2q63S12ewAAgPSmaWpumwVF
+aQiLgM3MnwQAANRGUJSOsAjIwvxJAABj80Q0ShIUpSUsAk5j/iQA8i3Z/QAADThJREFUAOAoQVF6
+wiKgWm53AwAAlgiK8hAWAU1zuxsAABCCoCglYRHQPYESAAD0TVCUlrAIIJg/CQAAWiUoSk9YBBDB
+/EkAADv6NZ6IxnM/NsO5ICjKQ1gEkOrLz+1uAADQndGCohCERQBFCZQAAGjBNE0aIYwZFIUgLAKo
+jvmTAADgfKMGRSEIiwCaY/4kAKAl5i1q85iNbuSgKARhEUCX3O4GAAD7jB4UhSAsAhiW290AACjW
+92ykukxQ9IuwCID3X+gV3e4Wuz0AALCXoOgPYREAu5k/CQCgL6POVyQo+kpYBEBW5k8CAKBmgqLv
+hEUAnM78SQDQN09Ea+c4jUZQ9J6wCIDqmT8JAIDUBEXzhEUAdMH8SQAAB/o3g1UVCYqWCYsAGIb5
+kwAAEBStExYBwBPzJwEAI1FR9HnKemsnLAKADdzuBgDQJkFRPGERACTmdjcAePO95YloVR6TIn2j
+Co67oGgbYREAnECgBABQhqBoO2ERAFTK/EkAQA4jzVNUS1D0eftsKjwSFgFAo86cP+kjXL92gP67
+OSAAQFVqCopaIywCgI6VCpQ+/r6uvkagBIB5i85t+1P6Iicdb0HRMcIiABhcqdvdBEoAQAmCouOE
+RQDAonuYNH3p/Ny+do4igqCoTtbMch6B1b+XEP43OSgAEOHsuYnOqCoSFKUhLAIADoupCEoVKIV/
+VzqewiQAGJKgKB1hEQBQRLFA6d+IXzEFSgB0aKSnnH3rQwiKkhIWAQDVmAuUrtfrr05wovmTBEoA
+0A9BUXrCIgCgHTEBzr+J5kcQKAGEEH7NO5OyYqX1J6KNXL2z9bwpQVCUh7AIAOhLTYGSMAkAihEU
+pSMsAgDGUypQUp0EwIDOqBwTFKUlLAIAeGctxHG7GwBUQVCUnrAIAGAPt7sBwDelq4oERXkIiwAA
+cnG7G9BRAGCSa2LOkx6NFhSFICwCADiXQAkAqjViUBSCsAgAoH7mTwKgcj1WFY0aFIUgLAIAaF8l
+8ydNP0O4/ONwANC+kYOiEIRFAABjKBQoTT+fOtrhGvWez/9ujg80wLxFLJ0bPRk9KApBWAQAwF2p
+291eO+V/X1dfI1ACoARB0S/CIgAA4qyESZfL5UtlUdLOu0AJoEo9VRUJiv4QFgEAkG7Q8E8I06OT
+fYvrnEcEQSmWI0wCYPY7RFD0hbAIAIBTxYQ4KQIl1UkA6ago6puwCACA6q2FOKWqk2K2BYB2CIre
+ExYBANC8UtVJscsRKNErT0Tjfh70QFA0T1gEAMAQagqUhEkA5xIULRMWAQDAfbBg/iSAWSqKxiEs
+AgCADcyfBNCus4Ki1/XWTlgEAAAJud0NtjFvUf1UFKVdbwuERQAAUJjb3QDKEhRtIywCAIAKCZSo
+VeonolH3se6BoGg7YREAADTK/EkAK59flQRFn7fPpsIjYREAAHTK/EnAXj1UFdUUFLVGWAQAAANz
+uxvQI0HRMcIiAABgkUCJV6nnLfJEtHqOaw8ERccJiwAAgMPMnwTUQFCUhrAIAADIzvxJUKeeKroE
+RekIiwAAgCq43S3xAPZpPwVk9E5QlJawCAAAaEYNt7u1GLx8/H0VGNHtvFCCovSERQAAQDdKVCe1
+WpkkMKJHgqI8hEUAAMBQSlQn1TBv0ud/t2/bkTIw8kS0Oo3choKidIRFAAAAzwO/CsKkmO2I3Zec
+gRFUc90KipISFgEAAGwZlJ44b9KekCdnYNRCFYtqpQGuSUFRcsIiAACAlAPXjPMm7b29TYUR3V5v
+gqIshEUAAAClB7iZAqWt74kJjKafjhdjGy0oCkFYBAAAUKV3IU6qW9y+L3PS4PDu+hgwKApBWAQA
+ANCMUvMlAeMGRSEIiwAAALqR6va2PXMZnTWwtl7r7Wm9tRAWAQAADCBn1ZEgwXqtty/Coozc9QsA
+AJwt5glqHwb01mu9p663NsIiAACAzsQERAb01mu9day3RsIiAACATpQKiUYc0Fuv9Y5EWJTY5+2m
+EQAAgHrGKAkDolEH9NZrvaMRFgEAAHQoR0g04oDeeq13RMIiAACATuQKiEYd0Fuv9Y7qL00AAACA
+Ab31Wi93wiIAAAAM6K3XenkQFgEAAGBAb73WW3C9tRMWAQAAYEBvvdZbaL0tEBYBAABgQG+91ltg
+va0QFgEAAGBAb73Wm3m9LREWAQAAMEuQYL3W2856UxEWAQAA8JYBvfVabzvrTekyTdO0+U2XSwgh
+hNvt5tMTAMjuer2GEELY0W2hZMfydx9xenSO9RWhFS3fLgMtKhkgffzuR11+/3dMf0plEQAAAAAP
+wiIAAAAAHn5oAgAAgLG1OKcKkI/KIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwYIJrAAAAivq4
+frz9+7mJtre8/vm1SxN3z71ubl1bl5n6PUe2K3adW4/DWvsfPb5737PlmJrc/T2VRQAAABSzNHB/
+929bX3/W9u/ZzjO2/+gxOrrcrcve856alt8qlUUAAAAUsVb18zpoX3r9/d8+rh+L1Sdbq19itu91
+uXu28/73qapz9tiyjyWWneo9Z+xvb1QWAQAAkF3M7WGxAczSa3Pac9vbnu08M7RYu+3r8/b5eM3W
+dj/aFjmO8xnnUQuERQAAABSzNQhZen3Mv81VK6UOZPZu52i3Qe1p99zhmYqi79yGBgAAABFShjqf
+t88vy4sNsfZMon10H9fmYzozbMndHqMSFgEAANCleyBzDzS2VBWVmDfoXfVTrsqnFPv4/HevYRd9
+ERYBAABApBwhzlxodHRC59T7WGM4pIIoD2ERAAAAxWy9bWntaWdrnquL7v8dY2sIcXQ7n9d55oTd
+e7Z9yzHds2+520OF1HcmuAYAACC7mKdOzT1ZbG0enVqeHrZlO1sLKO5PQXv9s8WeY5b7ONdyHtVG
+ZREAAABFPM9zs6UqaOn1MQP8Ek/T2rOde+ZFamVC55T7lqo9SsxD1QuVRQAAABSz9RHzex9Jb7+O
+i7l1b8utc3uqkfa8p6blt+oyTdO0+U2XSwghhNvtpgUBgOyu12sIIYQd3RZKdix/9xGnRwdcXxEA
+zvbxux91+f3fMf0plUUAAAAAPJizCACA09yrxl7NVbBvef3za5cq4udeN7eurctM/Z4j2xW7ztT7
+eH/t2nGda//YZS7tz1q77DlmAL1SWQQAwCmWBvbv/m3r68/a/j3becb2x+5jDccixTLn9qXm9oc9
+Pq4fi38gRrHKopikvvQvG3vWs+fLxS8yfpEBAOb7DDH9taXX3//ter0u9pP29AvXtu91uXu2c6mP
+d6RftsWWdR89FiXsOWZ7zw+ojcmaSaFIZVGqXx5S/nqzd3v37r9fZAAA1sOGd3+/9votPz6msue2
+tz3bWWvgcsaxOLq81tof4EzZK4u2/mq05XVry1/7ZWPLLw4pvlBTbXcNHQS/yAAAOfoae19/u90W
+K5zvP3jN9V9S9lf2budaFXlpe6uacrRnquW11P4AZ8paWbT1V6PUy6/h1wO/yPjCBQD6kzNcWqrk
+fve61z9792duOTX05e7bkONHyL3tD9CzIreh5f6CWftlo9aORMntzn1Puy9XAKBmr2HDliqSEkHK
+7XYTWpx8fmh/gD9+1LhRZ06SfOQLodQEhEe+BN+VYKdc9mtbqCoCAHqVo5/zroJmy5QKqfclV9+x
+tr7snvYH6NmPkXe+9nCn1Q6T0AgAiO2LbekjrD3tLKav8lwtErvuPU/KPbKdc/2qVo5diW0+crtd
+D+0PkNtfNW7UvQz0tRz0zKdb7Nnu5+2v5YumxPbMlfECALz2tbY+DGTtCbO1PBxky3a21E86eiy2
+PiE4VT+9l/YHKKVIZdHR0s21JyDs/WWjhvmM/CIDAIzouX+3pSpo6fUxfbsSc2nu2c49fdaUUzds
+DWy27mOq45dif1K1P0DPslYWbf3VKPXya3uKQ6rt9osMANCDrQ/7qPmhJr3u17uK8b3bnGo/j94F
+0Op5BVDSZZqmafObLpdNH55rQcJrBcrWx83HLv/19ak+/Pc+Qn7rdqfc19flbA1+UuwLAGz9rt3R
+baFkx/J3H/F+lD59/wPA6T5+96Muv/87pj9VZM6iFGn93mXU8uQGv8gAAAAALShSWQQAcITKokY6
+liqLAKA6eyqLfmg2AADoj2kCANhLWAQAAB0SBgGwl7BohV9kAAAAgJEIi1YIgwAAAICRCIsAAMji
+Y6VCGwCo01+aAAAAAIA7lUUAACR10QQA0PZ3+TRN0+Y3XXQBAIDydnRbKNmx1EcEgC76UyqLAAAo
+1vkEAOq3KyzSEQAAAADokwmuAQAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
+AA/CIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
+AA/CIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
+AA/CIgAAAAAe/g/10lQlA3JSSwAAAABJRU5ErkJggg==
index afc8a0dd2601d47425205c67977c793cc2f9bbd6..cea6fd3ed4289281bf8942485ad0923a59b84bc2 100644 (file)
@@ -178,11 +178,3 @@ in the frequency range from 87,5 to 108,0 MHz</title>
     </biblioentry>
 
   </bibliography>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index a86f7a04552914a5a460096703cc721dcdebc055..c79278acfb0ec6c1942808b788b1fe25b65fa726 100644 (file)
@@ -1168,6 +1168,8 @@ dheight = format.fmt.pix.height;
     </section>
   </section>
 
+  &sub-selection-api;
+
   <section id="streaming-par">
     <title>Streaming Parameters</title>
 
@@ -1195,11 +1197,3 @@ separate parameters for input and output devices.</para>
     <para>These ioctls are optional, drivers need not implement
 them. If so, they return the &EINVAL;.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index b68698f96e7f723b07c0005a2a1f955df724a73b..c736380b4647acc649f2203b09c394802cd6180e 100644 (file)
@@ -1082,7 +1082,7 @@ until the time in the timestamp field has arrived. I would like to
 follow SGI's lead, and adopt a multimedia timestamping system like
 their UST (Unadjusted System Time). See
 http://web.archive.org/web/*/http://reality.sgi.com
-/cpirazzi_engr/lg/time/intro.html. 
+/cpirazzi_engr/lg/time/intro.html.
 UST uses timestamps that are 64-bit signed integers
 (not struct timeval's) and given in nanosecond units. The UST clock
 starts at zero when the system is booted and runs continuously and
@@ -2376,6 +2376,23 @@ that used it. It was originally scheduled for removal in 2.6.35.
         <listitem>
          <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
         </listitem>
+        <listitem>
+         <para>Add selection API for extended control over cropping and
+composing. Does not affect the compatibility of current drivers and
+applications.  See <link linkend="selection-api"> selection API </link> for
+details.</para>
+        </listitem>
+      </orderedlist>
+    </section>
+
+    <section>
+      <title>V4L2 in Linux 3.3</title>
+      <orderedlist>
+        <listitem>
+         <para>Added <constant>V4L2_CID_ALPHA_COMPONENT</constant> control
+           to the <link linkend="control">User controls class</link>.
+         </para>
+        </listitem>
       </orderedlist>
     </section>
 
@@ -2489,6 +2506,9 @@ ioctls.</para>
         <listitem>
          <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
         </listitem>
+        <listitem>
+         <para>Selection API. <xref linkend="selection-api" /></para>
+        </listitem>
       </itemizedlist>
     </section>
 
@@ -2507,11 +2527,3 @@ interfaces and should not be implemented in new drivers.</para>
       </itemizedlist>
     </section>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 3bc5ee8b2c749ced60196d119e35b07295a42c45..a1be37897ad72682234a8aea99fdcc3fb172f9b8 100644 (file)
@@ -323,12 +323,6 @@ minimum value disables backlight compensation.</entry>
            <entry>Switch on or off the illuminator 1 or 2 of the device
                (usually a microscope).</entry>
          </row>
-         <row>
-           <entry><constant>V4L2_CID_LASTP1</constant></entry>
-           <entry></entry>
-           <entry>End of the predefined control IDs (currently
-<constant>V4L2_CID_ILLUMINATORS_2</constant> + 1).</entry>
-         </row>
          <row>
            <entry><constant>V4L2_CID_MIN_BUFFERS_FOR_CAPTURE</constant></entry>
            <entry>integer</entry>
@@ -345,6 +339,25 @@ and used as a hint to determine the number of OUTPUT buffers to pass to REQBUFS.
 The value is the minimum number of OUTPUT buffers that is necessary for hardware
 to work.</entry>
          </row>
+         <row id="v4l2-alpha-component">
+           <entry><constant>V4L2_CID_ALPHA_COMPONENT</constant></entry>
+           <entry>integer</entry>
+           <entry> Sets the alpha color component on the capture device or on
+           the capture buffer queue of a mem-to-mem device. When a mem-to-mem
+           device produces frame format that includes an alpha component
+           (e.g. <link linkend="rgb-formats">packed RGB image formats</link>)
+           and the alpha value is not defined by the mem-to-mem input data
+           this control lets you select the alpha component value of all
+           pixels. It is applicable to any pixel format that contains an alpha
+           component.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CID_LASTP1</constant></entry>
+           <entry></entry>
+           <entry>End of the predefined control IDs (currently
+             <constant>V4L2_CID_ALPHA_COMPONENT</constant> + 1).</entry>
+         </row>
          <row>
            <entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
            <entry></entry>
@@ -3329,6 +3342,16 @@ interface and may change in the future.</para>
                  <entry>The short circuit protection of the flash
                  controller has been triggered.</entry>
                </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
+                 <entry>Current in the LED power supply has exceeded the limit
+                 specific to the flash controller.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
+                 <entry>The flash controller has detected a short or open
+                 circuit condition on the indicator LED.</entry>
+               </row>
              </tbody>
            </entrytbl>
          </row>
@@ -3357,11 +3380,3 @@ interface and may change in the future.</para>
 
     </section>
 </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "common.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 2237c661f26aceb3a65ec5992bc0dc8e542c7752..e1c5f9406d6ac21208840e53b7648849416e8411 100644 (file)
@@ -108,11 +108,3 @@ linkend="mmap">memory mapping</link> or <link
 linkend="userp">user pointer</link>) I/O. See <xref
 linkend="io" /> for details.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 6e156dc45b94dd9d0cf74466ae3166a2d41d28fd..dca0ecd54dc699fa92e1cab272e665423712cd45 100644 (file)
@@ -16,11 +16,3 @@ Applications send data to be converted to the driver through a
 I/O.</para>
 
   <para>[to do]</para>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 9c243beba0e609556ae9d0c17d570554cdbce59a..2350a67c0710480470fc8693d407d51db18aca2e 100644 (file)
@@ -15,11 +15,3 @@ receive the result data either with &func-read; and &func-write;
 functions, or through the streaming I/O mechanism.</para>
 
   <para>[to do]</para>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index f14ae3fe107cf364b8c7d409eb7230f93257a73b..19f4becfae34bac8e377c92ca273d1776c148921 100644 (file)
@@ -41,11 +41,3 @@ intermediate step leading up to that information. See the documentation for the
 event you want to subscribe to whether this is applicable for that event or not.</para>
        </listitem>
       </orderedlist></para>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index c9a68a2ccd33bc840616854ac6f3194b6bd1751a..479d9433869aff1e18fdc12d3c2aa1d0bbee772b 100644 (file)
@@ -154,11 +154,3 @@ data flow. For more information see <xref linkend="crop" />.</para>
 however the framebuffer interface of the driver may support the
 <constant>FBIOBLANK</constant> ioctl.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 919e22c538542c001747b69a9c9639c511044f60..9130a3dc7880e4f906642f248c2de554d4b17752 100644 (file)
@@ -104,11 +104,3 @@ linkend="mmap">memory mapping</link> or <link
 linkend="userp">user pointer</link>) I/O. See <xref
 linkend="io" /> for details.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 92513cf791503aa4ddbb6771314a1f8102423aa7..40d1d76814394815f5067785dd31a5d5fb957b35 100644 (file)
@@ -369,11 +369,3 @@ reasons. <!-- video4linux-list@redhat.com on 22 Oct 2002 subject
     <para>To start or stop the frame buffer overlay applications call
 the &VIDIOC-OVERLAY; ioctl.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 73aa90b45b34f6b256676b4e9992ec8e7e261116..3e6ac73b36af5155b8716715a8005b3b8e6d7934 100644 (file)
@@ -47,11 +47,3 @@ depending on the selected frequency. The &VIDIOC-G-TUNER; or
 &VIDIOC-G-MODULATOR; ioctl
 reports the supported frequency range.</para>
   </section>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
- -->
index c5a70bdfaf27a5f7aacf697e1a3fd6471c0bb9cb..b788c72c885e04f16109ea17b2026061fdeb0e9f 100644 (file)
@@ -337,11 +337,3 @@ an &EBUSY; if the required hardware resources are temporarily
 unavailable, for example the device is already in use by another
 process.</para>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 2427f54397e7a28b45d8836befdaee9f8f00d323..38883a419e65674092aa4265ac4f637ff80211a4 100644 (file)
@@ -29,10 +29,10 @@ returned by the &VIDIOC-QUERYCAP; ioctl.  Any tuner that supports RDS
 will set the <constant>V4L2_TUNER_CAP_RDS</constant> flag in
 the <structfield>capability</structfield> field of &v4l2-tuner;.  If
 the driver only passes RDS blocks without interpreting the data
-the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be
+the <constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant> flag has to be
 set, see <link linkend="reading-rds-data">Reading RDS data</link>.
 For future use the
-flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> has also been
+flag <constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant> has also been
 defined. However, a driver for a radio tuner with this capability does
 not yet exist, so if you are planning to write such a driver you
 should discuss this on the linux-media mailing list: &v4l-ml;.</para>
@@ -52,9 +52,9 @@ field of &v4l2-modulator;.
 In order to enable the RDS transmission one must set the <constant>V4L2_TUNER_SUB_RDS</constant>
 bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.
 If the driver only passes RDS blocks without interpreting the data
-the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be set. If the
+the <constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant> flag has to be set. If the
 tuner is capable of handling RDS entities like program identification codes and radio
-text, the flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> should be set,
+text, the flag <constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant> should be set,
 see <link linkend="writing-rds-data">Writing RDS data</link> and
 <link linkend="fm-tx-controls">FM Transmitter Control Reference</link>.</para>
   </section>
@@ -194,11 +194,3 @@ as follows:</para>
       </tgroup>
     </table>
   </section>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
- -->
index 69e789fa7f7b450cd4d01f86ff36691dfa76ee43..548f8ea28dee97862c1c07a4e39947d7ee790160 100644 (file)
@@ -697,12 +697,3 @@ Sliced VBI services</link> for a description of the line payload.</entry>
 
   </section>
   </section>
-
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
- -->
index 414b1cfff9f48f50d27cd2784eb433c8fa4ef400..bd21c64d70f3dfc0a310bf2271028ae6d0af03d4 100644 (file)
@@ -27,11 +27,3 @@ kernel 2.6.37.</para>
 
   <para>Modern devices all use the <link linkend="raw-vbi">raw</link> or
 <link linkend="sliced">sliced</link> VBI API.</para>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 1f7eea5c4ec35de5ec6a5dbc56a80889b62743b3..eacafe312cd26e4cad3bcdbcc9bb398d50546f66 100644 (file)
@@ -198,11 +198,3 @@ devices with the videodev module.</para>
     <para>to do</para>
   </section>
 -->
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index dfb41cbbbec3dea5a98dd12d59f47b7dfc03a40c..232920d2f3c64c2f68a081fcc9f37173fe587cef 100644 (file)
@@ -60,11 +60,3 @@ descriptor.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 2de64be706f59fce8e1cabe42459b1bbbf196a60..4394184a1a6db2fb0653dd3974d9a6adf835c13f 100644 (file)
@@ -69,11 +69,3 @@ their respective function and parameters are specified in <xref
     the parameter remains unmodified.</para>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 786732b64bbde3b2aef4e087aae0ab01933b3bc1..f31ad71bf301adf19ebe656afca04305c9858337 100644 (file)
@@ -181,11 +181,3 @@ complete the request.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index e2c4190f9bb609a623a7f11994c138b66aee3ffc..860d49ca54a5c18af62d98229414f41b693777f6 100644 (file)
@@ -74,11 +74,3 @@ mapped yet.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 7595d07a8c72d4be090c982dc902ff96ab9357db..cf64e207c3ee36252a91fa0ad18ded5404c52c3b 100644 (file)
@@ -111,11 +111,3 @@ system has been reached.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index ec3c718f59631fc1afe0acd412e1ebe0b9c869a6..85cad8bff5ba79aecec18c721650d5994137bbc7 100644 (file)
@@ -117,11 +117,3 @@ than <constant>OPEN_MAX</constant>.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index a5089bf8873d88304798211e06152eed1fd5a894..e218bbfbd362ae7bc247913df8c478fa1002dbcd 100644 (file)
@@ -179,11 +179,3 @@ type of device.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index b6713623181f1fb396b8df3c2bbc08b4d5f3de94..e12a60d9bd85b079c857d2f31485d3f4f387de5a 100644 (file)
@@ -128,11 +128,3 @@ zero or greater than <constant>FD_SETSIZE</constant>.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 2c09c09371c3bc33555211e15ec677b96b12ee28..575207885726b4584e3234a0070acdec0f8e6614 100644 (file)
@@ -126,11 +126,3 @@ type of device.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 3f47df1aa54aba5d9c46ab57533a2ddfe9fe3461..b815929b5bbaf30ee62a7b2f987c54141a384702 100644 (file)
@@ -1282,11 +1282,3 @@ line, top field first. The bottom field is transmitted first.</entry>
        </mediaobject>
     </figure>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 3cb10ec5192947fd731831b00cc7e2b5fcb5c4df..d3b71e20003c354994d609b191146561c6578cb6 100644 (file)
@@ -158,10 +158,3 @@ still don't use libv4l.</para>
        </section>
 
 </section>
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 3b72bc6b2de7a29e1351e2814cc0edeb4326bb91..bee970d3f76d42553fdaca13798e59825b998d4e 100644 (file)
@@ -60,11 +60,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index ce4bc019e5c0351ee86ec12abff513571c9bf32f..aadae92c5d049369c8169d0725b5c9dccef95a43 100644 (file)
@@ -137,11 +137,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 873f670351819cff59b519b2955eb11fe9d6c4f4..84dd4fd7cb80bb76219c18484d8ca07f0d890653 100644 (file)
@@ -141,11 +141,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index c9e166d9ded8385f6bd7c4372d7dc0978bab3368..3fd3ce5df270563a7e9e1bfc26fa968498e9b1f4 100644 (file)
@@ -144,11 +144,3 @@ CbCr plane has as many pad bytes after its rows.</para>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 7a2855a526c1119a734a5c5a6d1b30f4de66c0c5..2f82b1da8dfed50185c33e2bd36d6e11800234d0 100644 (file)
@@ -64,11 +64,3 @@ layout of macroblocks</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 26094035fc04b1c13a3630979e3ae2b58fd5f86b..8ae1f8a810d0d1963f93d3311aa9baee12c90c0a 100644 (file)
@@ -164,11 +164,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 4db272b8a0d33305c1f9c785755dd4addf27b1d8..166c8d65e4f72ced74e3c359203f157316b62235 100644 (file)
@@ -428,8 +428,11 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
     <para>Bit 7 is the most significant bit. The value of a = alpha
 bits is undefined when reading from the driver, ignored when writing
 to the driver, except when alpha blending has been negotiated for a
-<link linkend="overlay">Video Overlay</link> or <link
-linkend="osd">Video Output Overlay</link>.</para>
+<link linkend="overlay">Video Overlay</link> or <link linkend="osd">
+Video Output Overlay</link> or when alpha component has been configured
+for a <link linkend="capture">Video Capture</link> by means of <link
+linkend="v4l2-alpha-component"> <constant>V4L2_CID_ALPHA_COMPONENT
+</constant> </link> control.</para>
 
     <example>
       <title><constant>V4L2_PIX_FMT_BGR24</constant> 4 &times; 4 pixel
@@ -930,11 +933,3 @@ See &v4l-dvb; for access instructions.</para>
 
   </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 3cab5d0ca75df71e6bc9e658ca50a541e1e4a138..33fa5a47a865f6c0ea8727ef6dd44fd2ba801baa 100644 (file)
@@ -234,11 +234,3 @@ linkend="osd">Video Output Overlay</link>.</para>
 
   </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 519a9efbac108b0ca61957027204dc2f2d4286f4..6494b05d84a147f4ddb1ee1d91e4fcfcee1b662b 100644 (file)
@@ -81,11 +81,3 @@ pixel image</title>
     </example>
   </refsect1>
 </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 5fe84ecc2ebeb77927e6bed6263d64e3518b15ec..5eaf2b42d3f7069d296c8760f6e9c08ddc555be8 100644 (file)
@@ -65,11 +65,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index d67a472b0880b45e61a420b57854e6f0a41b9c26..fee65dca79c5209a2b29288388c5c8e1eb574faf 100644 (file)
@@ -65,11 +65,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 0cdf13b8ac1ca71a3a70b8bd3e1284ed3cf14c93..19727ab4c75752035bc59c89b693a0a3242c95cf 100644 (file)
@@ -65,11 +65,3 @@ columns and rows.</para>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 816c8d467c16b0d657abe3118f0cf00643426918..b1f6801a17ff7cde887aee7775c77c1acd0fc901 100644 (file)
@@ -118,11 +118,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 61f12a5e68d92dba5a9b3b88ec24c2cb2caf263f..82803408b38923cab052208e830c6434e266d329 100644 (file)
@@ -118,11 +118,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index d584040150784472191303f413bdcd9315e74d7c..ff4f727d56242c26e1c547bfb1356f36992b63f1 100644 (file)
@@ -79,11 +79,3 @@ pixel image</title>
     </example>
   </refsect1>
 </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 73c8536efb05b8e868208786611501d8f6f394df..98dcb91d29172af0e6aa7d2100a79637b9740245 100644 (file)
@@ -147,11 +147,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 8eb4a193d7707c6ab6cd9aa5a9ddc33ad4fad5cf..0869dce5f92c76e49217e6824685ad81ef44e6a5 100644 (file)
@@ -131,11 +131,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 00e0960a986902bb2e467a4ab2ae6c3b51a62845..086dc731bf0251a5096b66330bd4d9b3e832670e 100644 (file)
@@ -145,11 +145,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 42d7de5e456d77a22d3911f1c85c5149b7ff8d82..48649fac15969e2ff756e4ee30682c7aa43a4afa 100644 (file)
@@ -147,11 +147,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index f5d8f57495c840e9117b480ac68dc3dc5ab8c1b8..9957863daf18d4a4627a74b52fbfe3bd1141b87e 100644 (file)
@@ -152,11 +152,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 4348bd9f0d01ff015eb29527094cade95289c81c..4ce6463fe0a57f226f22ea4788a9bbd70c5aec28 100644 (file)
@@ -151,11 +151,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index bdb2ffacbbccaf7b500600750efaea0a839cdb31..58384092251a4dcf8bf2e4210f2ded56ad7bd5c1 100644 (file)
@@ -118,11 +118,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index 40d17ae39dde0cd399c54d35d96cccce25149f4b..bfffdc76d3daffbaa4e58828ba1cfb7f3e5f18e5 100644 (file)
@@ -118,11 +118,3 @@ pixel image</title>
        </example>
       </refsect1>
     </refentry>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "pixfmt.sgml"
-indent-tabs-mode: nil
-End:
-  -->
index aef4615fb07b65bdd8ad0cd2ceb95fd8f405d050..31eaae2469f9b4ee48f1f13b1fbcf956f8fb9f54 100644 (file)
@@ -891,6 +891,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
            <entry>'M310'</entry>
            <entry>Compressed BGGR Bayer format used by the gspca driver.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-JL2005BCD">
+           <entry><constant>V4L2_PIX_FMT_JL2005BCD</constant></entry>
+           <entry>'JL20'</entry>
+           <entry>JPEG compressed RGGB Bayer format used by the gspca driver.</entry>
+         </row>
          <row id="V4L2-PIX-FMT-OV511">
            <entry><constant>V4L2_PIX_FMT_OV511</constant></entry>
            <entry>'O511'</entry>
@@ -998,11 +1003,3 @@ the other bits are set to 0.</entry>
       </tgroup>
     </table>
   </section>
-
-  <!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
-  -->
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
new file mode 100644 (file)
index 0000000..2f0bdb4
--- /dev/null
@@ -0,0 +1,321 @@
+<section id="selection-api">
+
+  <title>Experimental API for cropping, composing and scaling</title>
+
+      <note>
+       <title>Experimental</title>
+
+       <para>This is an <link linkend="experimental">experimental</link>
+interface and may change in the future.</para>
+      </note>
+
+  <section>
+    <title>Introduction</title>
+
+<para>Some video capture devices can sample a subsection of a picture and
+shrink or enlarge it to an image of arbitrary size. Next, the devices can
+insert the image into larger one. Some video output devices can crop part of an
+input image, scale it up or down and insert it at an arbitrary scan line and
+horizontal offset into a video signal. We call these abilities cropping,
+scaling and composing.</para>
+
+<para>On a video <emphasis>capture</emphasis> device the source is a video
+signal, and the cropping target determine the area actually sampled. The sink
+is an image stored in a memory buffer.  The composing area specifies which part
+of the buffer is actually written to by the hardware. </para>
+
+<para>On a video <emphasis>output</emphasis> device the source is an image in a
+memory buffer, and the cropping target is a part of an image to be shown on a
+display. The sink is the display or the graphics screen. The application may
+select the part of display where the image should be displayed. The size and
+position of such a window is controlled by the compose target.</para>
+
+<para>Rectangles for all cropping and composing targets are defined even if the
+device does supports neither cropping nor composing. Their size and position
+will be fixed in such a case. If the device does not support scaling then the
+cropping and composing rectangles have the same size.</para>
+
+  </section>
+
+    <section>
+      <title>Selection targets</title>
+
+      <figure id="sel-targets-capture">
+       <title>Cropping and composing targets</title>
+       <mediaobject>
+         <imageobject>
+           <imagedata fileref="selection.png" format="PNG" />
+         </imageobject>
+         <textobject>
+           <phrase>Targets used by a cropping, composing and scaling
+            process</phrase>
+         </textobject>
+       </mediaobject>
+      </figure>
+    </section>
+
+  <section>
+
+  <title>Configuration</title>
+
+<para>Applications can use the <link linkend="vidioc-g-selection">selection
+API</link> to select an area in a video signal or a buffer, and to query for
+default settings and hardware limits.</para>
+
+<para>Video hardware can have various cropping, composing and scaling
+limitations. It may only scale up or down, support only discrete scaling
+factors, or have different scaling abilities in the horizontal and vertical
+directions. Also it may not support scaling at all. At the same time the
+cropping/composing rectangles may have to be aligned, and both the source and
+the sink may have arbitrary upper and lower size limits. Therefore, as usual,
+drivers are expected to adjust the requested parameters and return the actual
+values selected. An application can control the rounding behaviour using <link
+linkend="v4l2-sel-flags"> constraint flags </link>.</para>
+
+   <section>
+
+   <title>Configuration of video capture</title>
+
+<para>See figure <xref linkend="sel-targets-capture" /> for examples of the
+selection targets available for a video capture device.  It is recommended to
+configure the cropping targets before to the composing targets.</para>
+
+<para>The range of coordinates of the top left corner, width and height of
+areas that can be sampled is given by the <constant> V4L2_SEL_TGT_CROP_BOUNDS
+</constant> target. It is recommended for the driver developers to put the
+top/left corner at position <constant> (0,0) </constant>.  The rectangle's
+coordinates are expressed in pixels.</para>
+
+<para>The top left corner, width and height of the source rectangle, that is
+the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP_ACTIVE
+</constant> target. It uses the same coordinate system as <constant>
+V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
+completely inside the capture boundaries. The driver may further adjust the
+requested size and/or position according to hardware limitations.</para>
+
+<para>Each capture device has a default source rectangle, given by the
+<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant> target. This rectangle shall
+over what the driver writer considers the complete picture.  Drivers shall set
+the active crop rectangle to the default when the driver is first loaded, but
+not later.</para>
+
+<para>The composing targets refer to a memory buffer. The limits of composing
+coordinates are obtained using <constant> V4L2_SEL_TGT_COMPOSE_BOUNDS
+</constant>.  All coordinates are expressed in pixels. The rectangle's top/left
+corner must be located at position <constant> (0,0) </constant>. The width and
+height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
+</para>
+
+<para>The part of a buffer into which the image is inserted by the hardware is
+controlled by the <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.
+The rectangle's coordinates are also expressed in the same coordinate system as
+the bounds rectangle. The composing rectangle must lie completely inside bounds
+rectangle. The driver must adjust the composing rectangle to fit to the
+bounding limits. Moreover, the driver can perform other adjustments according
+to hardware limitations. The application can control rounding behaviour using
+<link linkend="v4l2-sel-flags"> constraint flags </link>.</para>
+
+<para>For capture devices the default composing rectangle is queried using
+<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
+bounding rectangle.</para>
+
+<para>The part of a buffer that is modified by the hardware is given by
+<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
+defined using <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> plus all
+padding data modified by hardware during insertion process. All pixels outside
+this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
+content of pixels that lie inside the padded area but outside active area is
+undefined. The application can use the padded and active rectangles to detect
+where the rubbish pixels are located and remove them if needed.</para>
+
+   </section>
+
+   <section>
+
+   <title>Configuration of video output</title>
+
+<para>For output devices targets and ioctls are used similarly to the video
+capture case. The <emphasis> composing </emphasis> rectangle refers to the
+insertion of an image into a video signal. The cropping rectangles refer to a
+memory buffer. It is recommended to configure the composing targets before to
+the cropping targets.</para>
+
+<para>The cropping targets refer to the memory buffer that contains an image to
+be inserted into a video signal or graphical screen. The limits of cropping
+coordinates are obtained using <constant> V4L2_SEL_TGT_CROP_BOUNDS </constant>.
+All coordinates are expressed in pixels. The top/left corner is always point
+<constant> (0,0) </constant>.  The width and height is equal to the image size
+specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
+
+<para>The top left corner, width and height of the source rectangle, that is
+the area from which image date are processed by the hardware, is given by the
+<constant> V4L2_SEL_TGT_CROP_ACTIVE </constant>. Its coordinates are expressed
+in in the same coordinate system as the bounds rectangle. The active cropping
+area must lie completely inside the crop boundaries and the driver may further
+adjust the requested size and/or position according to hardware
+limitations.</para>
+
+<para>For output devices the default cropping rectangle is queried using
+<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant>. It is usually equal to the
+bounding rectangle.</para>
+
+<para>The part of a video signal or graphics display where the image is
+inserted by the hardware is controlled by <constant>
+V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.  The rectangle's coordinates
+are expressed in pixels. The composing rectangle must lie completely inside the
+bounds rectangle.  The driver must adjust the area to fit to the bounding
+limits.  Moreover, the driver can perform other adjustments according to
+hardware limitations. </para>
+
+<para>The device has a default composing rectangle, given by the <constant>
+V4L2_SEL_TGT_COMPOSE_DEFAULT </constant> target. This rectangle shall cover what
+the driver writer considers the complete picture. It is recommended for the
+driver developers to put the top/left corner at position <constant> (0,0)
+</constant>. Drivers shall set the active composing rectangle to the default
+one when the driver is first loaded.</para>
+
+<para>The devices may introduce additional content to video signal other than
+an image from memory buffers.  It includes borders around an image. However,
+such a padded area is driver-dependent feature not covered by this document.
+Driver developers are encouraged to keep padded rectangle equal to active one.
+The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
+</constant> identifier.  It must contain all pixels from the <constant>
+V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para>
+
+   </section>
+
+   <section>
+
+     <title>Scaling control.</title>
+
+<para>An application can detect if scaling is performed by comparing the width
+and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP_ACTIVE
+</constant> and <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> targets. If
+these are not equal then the scaling is applied. The application can compute
+the scaling ratios using these values.</para>
+
+   </section>
+
+  </section>
+
+  <section>
+
+    <title>Comparison with old cropping API.</title>
+
+<para>The selection API was introduced to cope with deficiencies of previous
+<link linkend="crop"> API </link>, that was designed to control simple capture
+devices. Later the cropping API was adopted by video output drivers. The ioctls
+are used to select a part of the display were the video signal is inserted. It
+should be considered as an API abuse because the described operation is
+actually the composing.  The selection API makes a clear distinction between
+composing and cropping operations by setting the appropriate targets.  The V4L2
+API lacks any support for composing to and cropping from an image inside a
+memory buffer.  The application could configure a capture device to fill only a
+part of an image by abusing V4L2 API.  Cropping a smaller image from a larger
+one is achieved by setting the field <structfield>
+&v4l2-pix-format;::bytesperline </structfield>.  Introducing an image offsets
+could be done by modifying field <structfield> &v4l2-buffer;::m:userptr
+</structfield> before calling <constant> VIDIOC_QBUF </constant>. Those
+operations should be avoided because they are not portable (endianness), and do
+not work for macroblock and Bayer formats and mmap buffers.  The selection API
+deals with configuration of buffer cropping/composing in a clear, intuitive and
+portable way.  Next, with the selection API the concepts of the padded target
+and constraints flags are introduced.  Finally, <structname> &v4l2-crop;
+</structname> and <structname> &v4l2-cropcap; </structname> have no reserved
+fields. Therefore there is no way to extend their functionality.  The new
+<structname> &v4l2-selection; </structname> provides a lot of place for future
+extensions.  Driver developers are encouraged to implement only selection API.
+The former cropping API would be simulated using the new one. </para>
+
+  </section>
+
+   <section>
+      <title>Examples</title>
+      <example>
+       <title>Resetting the cropping parameters</title>
+
+       <para>(A video capture device is assumed; change <constant>
+V4L2_BUF_TYPE_VIDEO_CAPTURE </constant> for other devices; change target to
+<constant> V4L2_SEL_TGT_COMPOSE_* </constant> family to configure composing
+area)</para>
+
+       <programlisting>
+
+       &v4l2-selection; sel = {
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .target = V4L2_SEL_TGT_CROP_DEFAULT,
+       };
+       ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel);
+       if (ret)
+               exit(-1);
+       sel.target = V4L2_SEL_TGT_CROP_ACTIVE;
+       ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
+       if (ret)
+               exit(-1);
+
+        </programlisting>
+      </example>
+
+      <example>
+       <title>Simple downscaling</title>
+       <para>Setting a composing area on output of size of <emphasis> at most
+</emphasis> half of limit placed at a center of a display.</para>
+       <programlisting>
+
+       &v4l2-selection; sel = {
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               .target = V4L2_SEL_TGT_COMPOSE_BOUNDS,
+       };
+       struct v4l2_rect r;
+
+       ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel);
+       if (ret)
+               exit(-1);
+       /* setting smaller compose rectangle */
+       r.width = sel.r.width / 2;
+       r.height = sel.r.height / 2;
+       r.left = sel.r.width / 4;
+       r.top = sel.r.height / 4;
+       sel.r = r;
+       sel.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+       sel.flags = V4L2_SEL_FLAG_LE;
+       ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
+       if (ret)
+               exit(-1);
+
+        </programlisting>
+      </example>
+
+      <example>
+       <title>Querying for scaling factors</title>
+       <para>A video output device is assumed; change <constant>
+V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
+       <programlisting>
+
+       &v4l2-selection; compose = {
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               .target = V4L2_SEL_TGT_COMPOSE_ACTIVE,
+       };
+       &v4l2-selection; crop = {
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               .target = V4L2_SEL_TGT_CROP_ACTIVE,
+       };
+       double hscale, vscale;
+
+       ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;compose);
+       if (ret)
+               exit(-1);
+       ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;crop);
+       if (ret)
+               exit(-1);
+
+       /* computing scaling factors */
+       hscale = (double)compose.r.width / crop.r.width;
+       vscale = (double)compose.r.height / crop.r.height;
+
+       </programlisting>
+      </example>
+
+   </section>
+
+</section>
index 2ab365c10fb91083b9defe3e57d215cae8688450..e97c512861bb352320d8be206945a2bb5c82d8b7 100644 (file)
@@ -501,6 +501,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-g-output;
     &sub-g-parm;
     &sub-g-priority;
+    &sub-g-selection;
     &sub-g-sliced-vbi-cap;
     &sub-g-std;
     &sub-g-tuner;
index 1d31427edd1b8510b01f5fdce56216c82f6f751d..0be17c232d3a6a30cf2b8b0099fd3a9ce3907151 100644 (file)
@@ -228,11 +228,3 @@ is out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 71d373b6d36a31ac50bed40aaebf0c67a51eff23..347d142e74313230518224aba7d69f7368fcf53d 100644 (file)
@@ -156,11 +156,3 @@ bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 476fe1d2bba0f52db78753e3a39eeaf79333a20a..9b8efcd6e947058e2f8cb1f8b55cf363bea7c8a2 100644 (file)
@@ -311,11 +311,3 @@ out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index a281d26a195fbb501fcd96059080b8965ff7a69f..a64d5ef103faf959dfd2c71398f00f0aa162eef7 100644 (file)
@@ -196,11 +196,3 @@ is out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 95803fe2c8e4336a8e110d87a0570d1de98ef378..3a5fc5405f96a869f0ff93262211c430dcbd4123 100644 (file)
@@ -381,11 +381,3 @@ is out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 5146d00782e339468763cc853849ee12879bafb2..12b1d0503e261ecabd76c370b8d6498306535ac4 100644 (file)
@@ -127,11 +127,3 @@ this control belongs to.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 5122ce87e0b806a490175bec8600662b7f2a0cd5..6f1f9a629dc34d1508bd550342d810f05f2b5028 100644 (file)
@@ -312,10 +312,3 @@ to store the payload and this error code is returned.</para>
   </refsect1>
 </refentry>
 
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 055718231bc18ce81ddb9287d5633a5ab412388c..93817f33703305beae49acafa52b1bceb0613dd2 100644 (file)
@@ -295,7 +295,8 @@ set this field to zero.</entry>
            <entry>The device is capable of non-destructive overlays.
 When the driver clears this flag, only destructive overlays are
 supported. There are no drivers yet which support both destructive and
-non-destructive overlays.</entry>
+non-destructive overlays. Video Output Overlays are in practice always
+non-destructive.</entry>
          </row>
          <row>
            <entry><constant>V4L2_FBUF_CAP_CHROMAKEY</constant></entry>
@@ -339,8 +340,8 @@ blending makes no sense for destructive overlays.</entry>
          <row>
            <entry><constant>V4L2_FBUF_CAP_SRC_CHROMAKEY</constant></entry>
            <entry>0x0080</entry>
-           <entry>The device supports Source Chroma-keying. Framebuffer pixels
-with the chroma-key colors are replaced by video pixels, which is exactly opposite of
+           <entry>The device supports Source Chroma-keying. Video pixels
+with the chroma-key colors are replaced by framebuffer pixels, which is exactly opposite of
 <constant>V4L2_FBUF_CAP_CHROMAKEY</constant></entry>
          </row>
        </tbody>
@@ -356,7 +357,9 @@ with the chroma-key colors are replaced by video pixels, which is exactly opposi
            <entry><constant>V4L2_FBUF_FLAG_PRIMARY</constant></entry>
            <entry>0x0001</entry>
            <entry>The framebuffer is the primary graphics surface.
-In other words, the overlay is destructive. [?]</entry>
+In other words, the overlay is destructive. This flag is typically set by any
+driver that doesn't have the <constant>V4L2_FBUF_CAP_EXTERNOVERLAY</constant>
+capability and it is cleared otherwise.</entry>
          </row>
          <row>
            <entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry>
@@ -366,9 +369,8 @@ size as the capture. [?]</entry>
          </row>
          <row>
            <entry spanname="hspan">The purpose of
-<constant>V4L2_FBUF_FLAG_PRIMARY</constant> and
 <constant>V4L2_FBUF_FLAG_OVERLAY</constant> was never quite clear.
-Most drivers seem to ignore these flags. For compatibility with the
+Most drivers seem to ignore this flag. For compatibility with the
 <wordasword>bttv</wordasword> driver applications should set the
 <constant>V4L2_FBUF_FLAG_OVERLAY</constant> flag.</entry>
          </row>
index 062d720690906b3993327e88fdd05db47f249037..16431813bebd253f87965029088ee733328c36e5 100644 (file)
@@ -135,11 +135,3 @@ wrong.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 15ce660f0f5a6d47dadb062c3754fb502adfc54d..7f4ac7e41fa8765d709794a130a2f11091b7c98a 100644 (file)
@@ -236,11 +236,3 @@ mode.</entry>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 8f5e3da7002fee8a68279dd1ee4a30939d6776e3..6a81b4fe95383eebb7f7d5288fc21adbb8b16032 100644 (file)
@@ -133,11 +133,3 @@ priority.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
new file mode 100644 (file)
index 0000000..a9d36e0
--- /dev/null
@@ -0,0 +1,304 @@
+<refentry id="vidioc-g-selection">
+
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_G_SELECTION, VIDIOC_S_SELECTION</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_G_SELECTION</refname>
+    <refname>VIDIOC_S_SELECTION</refname>
+    <refpurpose>Get or set one of the selection rectangles</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_selection *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_G_SELECTION, VIDIOC_S_SELECTION</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>The ioctls are used to query and configure selection rectangles.</para>
+
+<para> To query the cropping (composing) rectangle set <structfield>
+&v4l2-selection;::type </structfield> to the respective buffer type.  Do not
+use multiplanar buffers.  Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
+</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+</constant>.  Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
+<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>.  The next step is
+setting <structfield> &v4l2-selection;::target </structfield> to value
+<constant> V4L2_SEL_TGT_CROP_ACTIVE </constant> (<constant>
+V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>).  Please refer to table <xref
+linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
+targets.  Fields <structfield> &v4l2-selection;::flags </structfield> and
+<structfield> &v4l2-selection;::reserved </structfield> are ignored and they
+must be filled with zeros.  The driver fills the rest of the structure or
+returns &EINVAL; if incorrect buffer type or target was used. If cropping
+(composing) is not supported then the active rectangle is not mutable and it is
+always equal to the bounds rectangle.  Finally, structure <structfield>
+&v4l2-selection;::r </structfield> is filled with the current cropping
+(composing) coordinates. The coordinates are expressed in driver-dependent
+units. The only exception are rectangles for images in raw formats, whose
+coordinates are always expressed in pixels.  </para>
+
+<para> To change the cropping (composing) rectangle set <structfield>
+&v4l2-selection;::type </structfield> to the respective buffer type.  Do not
+use multiplanar buffers.  Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
+</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+</constant>.  Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
+<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>.  The next step is
+setting <structfield> &v4l2-selection;::target </structfield> to value
+<constant> V4L2_SEL_TGT_CROP_ACTIVE </constant> (<constant>
+V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref
+linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
+targets.  Set desired active area into the field <structfield>
+&v4l2-selection;::r </structfield>.  Field <structfield>
+&v4l2-selection;::reserved </structfield> is ignored and must be filled with
+zeros.  The driver may adjust the rectangle coordinates. An application may
+introduce constraints to control rounding behaviour. Set the field
+<structfield> &v4l2-selection;::flags </structfield> to one of values:
+
+<itemizedlist>
+  <listitem>
+<para><constant>0</constant> - The driver can adjust the rectangle size freely
+and shall choose a crop/compose rectangle as close as possible to the requested
+one.</para>
+  </listitem>
+  <listitem>
+<para><constant>V4L2_SEL_FLAG_GE</constant> - The driver is not allowed to
+shrink the rectangle.  The original rectangle must lay inside the adjusted
+one.</para>
+  </listitem>
+  <listitem>
+<para><constant>V4L2_SEL_FLAG_LE</constant> - The driver is not allowed to
+enlarge the rectangle.  The adjusted rectangle must lay inside the original
+one.</para>
+  </listitem>
+  <listitem>
+<para><constant>V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE</constant> - The driver
+must choose the size exactly the same as in the requested rectangle.</para>
+  </listitem>
+</itemizedlist>
+
+Please refer to <xref linkend="sel-const-adjust" />.
+
+</para>
+
+<para> The driver may have to adjusts the requested dimensions against hardware
+limits and other parts as the pipeline, i.e. the bounds given by the
+capture/output window or TV display. The closest possible values of horizontal
+and vertical offset and sizes are chosen according to following priority:
+
+<orderedlist>
+  <listitem>
+    <para>Satisfy constraints from <structfield>&v4l2-selection;::flags</structfield>.</para>
+  </listitem>
+  <listitem>
+    <para>Adjust width, height, left, and top to hardware limits and alignments.</para>
+  </listitem>
+  <listitem>
+    <para>Keep center of adjusted rectangle as close as possible to the original one.</para>
+  </listitem>
+  <listitem>
+    <para>Keep width and height as close as possible to original ones.</para>
+  </listitem>
+  <listitem>
+    <para>Keep horizontal and vertical offset as close as possible to original ones.</para>
+  </listitem>
+</orderedlist>
+
+On success the field <structfield> &v4l2-selection;::r </structfield> contains
+the adjusted rectangle. When the parameters are unsuitable the application may
+modify the cropping (composing) or image parameters and repeat the cycle until
+satisfactory parameters have been negotiated. If constraints flags have to be
+violated at then ERANGE is returned. The error indicates that <emphasis> there
+exist no rectangle </emphasis> that satisfies the constraints.</para>
+
+  </refsect1>
+
+  <refsect1>
+    <table frame="none" pgwide="1" id="v4l2-sel-target">
+      <title>Selection targets.</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+            <entry><constant>V4L2_SEL_TGT_CROP_ACTIVE</constant></entry>
+            <entry>0</entry>
+            <entry>area that is currently cropped by hardware</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_CROP_DEFAULT</constant></entry>
+            <entry>1</entry>
+            <entry>suggested cropping rectangle that covers the "whole picture"</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_CROP_BOUNDS</constant></entry>
+            <entry>2</entry>
+            <entry>limits for the cropping rectangle</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_COMPOSE_ACTIVE</constant></entry>
+            <entry>256</entry>
+            <entry>area to which data are composed by hardware</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant></entry>
+            <entry>257</entry>
+            <entry>suggested composing rectangle that covers the "whole picture"</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
+            <entry>258</entry>
+            <entry>limits for the composing rectangle</entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant></entry>
+            <entry>259</entry>
+            <entry>the active area and all padding pixels that are inserted or modified by the hardware</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    <table frame="none" pgwide="1" id="v4l2-sel-flags">
+      <title>Selection constraint flags</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+            <entry><constant>V4L2_SEL_FLAG_GE</constant></entry>
+            <entry>0x00000001</entry>
+            <entry>indicate that adjusted rectangle must contain a rectangle from <structfield>&v4l2-selection;::r</structfield></entry>
+         </row>
+         <row>
+            <entry><constant>V4L2_SEL_FLAG_LE</constant></entry>
+            <entry>0x00000002</entry>
+            <entry>indicate that adjusted rectangle must be inside a rectangle from <structfield>&v4l2-selection;::r</structfield></entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+    <section>
+      <figure id="sel-const-adjust">
+       <title>Size adjustments with constraint flags.</title>
+       <mediaobject>
+         <imageobject>
+           <imagedata fileref="constraints.png" format="PNG" />
+         </imageobject>
+         <textobject>
+           <phrase>Behaviour of rectangle adjustment for different constraint
+            flags.</phrase>
+         </textobject>
+       </mediaobject>
+      </figure>
+    </section>
+
+  <refsect1>
+    <table pgwide="1" frame="none" id="v4l2-selection">
+      <title>struct <structname>v4l2_selection</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>type</structfield></entry>
+           <entry>Type of the buffer (from &v4l2-buf-type;)</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>target</structfield></entry>
+            <entry>used to select between <link linkend="v4l2-sel-target"> cropping and composing rectangles </link></entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>flags</structfield></entry>
+            <entry>control over coordinates adjustments, refer to <link linkend="v4l2-sel-flags">selection flags</link></entry>
+         </row>
+         <row>
+           <entry>&v4l2-rect;</entry>
+           <entry><structfield>r</structfield></entry>
+           <entry>selection rectangle</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved[9]</structfield></entry>
+           <entry>Reserved fields for future use</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>EINVAL</errorcode></term>
+       <listitem>
+         <para>The buffer <structfield> &v4l2-selection;::type </structfield>
+or <structfield> &v4l2-selection;::target </structfield> is not supported, or
+the <structfield> &v4l2-selection;::flags </structfield> are invalid.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><errorcode>ERANGE</errorcode></term>
+       <listitem>
+         <para>it is not possible to adjust a rectangle <structfield>
+&v4l2-selection;::r </structfield> that satisfies all contraints from
+<structfield> &v4l2-selection;::flags </structfield>.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><errorcode>EBUSY</errorcode></term>
+       <listitem>
+         <para>it is not possible to apply change of selection rectangle at the moment.
+Usually because streaming is in progress.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+</refentry>
index 37996f25b5d406bd237048c5bb77589d68dc1413..99ff1a016220aee8461cddf088de122057c29ecf 100644 (file)
@@ -88,11 +88,3 @@ standards.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index bd98c734c06b68f34be7a1ce40c426fb2befdd23..91ec2fb658f875dbe76e76465994dcaba9cbb455 100644 (file)
@@ -318,6 +318,16 @@ standard.</para><!-- FIXME what if PAL+NTSC and Bi but not SAP? --></entry>
        <entry>RDS capture is supported. This capability is only valid for
 radio tuners.</entry>
          </row>
+         <row>
+       <entry><constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant></entry>
+       <entry>0x0100</entry>
+       <entry>The RDS data is passed as unparsed RDS blocks.</entry>
+         </row>
+         <row>
+       <entry><constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant></entry>
+       <entry>0x0200</entry>
+       <entry>The RDS data is parsed by the hardware and set via controls.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
@@ -525,11 +535,3 @@ out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 5c104d42d31cd9b3dd2860c1bf3db221ed911f2c..6e414d7b6df759f83f45ad34256c5ace012a6543 100644 (file)
@@ -100,11 +100,3 @@ supported, or the <structfield>index</structfield> is out of bounds.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 0ac0057a51c4c9cb47da092159b955eb1ff11ad9..36660d311b5129d21f3690cbe292394bb457c38d 100644 (file)
@@ -443,11 +443,3 @@ or this particular menu item is not supported by the driver.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index c30dcc4232c0597faaa9f33a970eafe345cd5e75..e013da845b1192c7f4dca179814e4a4d41eeb81d 100644 (file)
@@ -125,11 +125,3 @@ wrong.</para>
     </variablelist>
   </refsect1>
 </refentry>
-
-<!--
-Local Variables:
-mode: sgml
-sgml-parent-document: "v4l2.sgml"
-indent-tabs-mode: nil
-End:
--->
index 96b690348ba14290f10235b94d6e13e4cc2d329d..cf44eb6499b418c3fd28339b52d53b3467cbfe23 100644 (file)
@@ -102,9 +102,15 @@ or
        make coccicheck COCCI=<my_SP.cocci> MODE=report
 
 
- Using Coccinelle on (modified) files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Controlling Which Files are Processed by Coccinelle
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+By default the entire kernel source tree is checked.
+
+To apply Coccinelle to a specific directory, M= can be used.
+For example, to check drivers/net/wireless/ one may write:
 
+    make coccicheck M=drivers/net/wireless/
+    
 To apply Coccinelle on a file basis, instead of a directory basis, the
 following command may be used:
 
index e67be7afc78b481d4dc42553bc555690e34c898e..d1d4a179a38221a5d0da86ecc8d5d44c68c1f1fc 100755 (executable)
@@ -27,8 +27,8 @@ use IO::Handle;
                "or51211", "or51132_qam", "or51132_vsb", "bluebird",
                "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
                "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
-               "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "tda10071",
-               "it9135" );
+               "lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
+               "drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137");
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -644,6 +644,24 @@ sub drxk {
     "$fwfile"
 }
 
+sub drxk_hauppauge_hvr930c {
+    my $url = "http://www.wintvcd.co.uk/drivers/";
+    my $zipfile = "HVR-9x0_5_10_325_28153_SIGNED.zip";
+    my $hash = "83ab82e7e9480ec8bf1ae0155ca63c88";
+    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+    my $drvfile = "HVR-900/emOEM.sys";
+    my $fwfile = "dvb-usb-hauppauge-hvr930c-drxk.fw";
+
+    checkstandard();
+
+    wgetfile($zipfile, $url . $zipfile);
+    verify($zipfile, $hash);
+    unzip($zipfile, $tmpdir);
+    extract("$tmpdir/$drvfile", 0x117b0, 42692, "$fwfile");
+
+    "$fwfile"
+}
+
 sub drxk_terratec_h5 {
     my $url = "http://www.linuxtv.org/downloads/firmware/";
     my $hash = "19000dada8e2741162ccc50cc91fa7f1";
@@ -658,6 +676,26 @@ sub drxk_terratec_h5 {
 }
 
 sub it9135 {
+       my $sourcefile = "dvb-usb-it9135.zip";
+       my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
+       my $hash = "1e55f6c8833f1d0ae067c2bb2953e6a9";
+       my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
+       my $outfile = "dvb-usb-it9135.fw";
+       my $fwfile1 = "dvb-usb-it9135-01.fw";
+       my $fwfile2 = "dvb-usb-it9135-02.fw";
+
+       checkstandard();
+
+       wgetfile($sourcefile, $url);
+       unzip($sourcefile, $tmpdir);
+       verify("$tmpdir/$outfile", $hash);
+       extract("$tmpdir/$outfile", 64, 8128, "$fwfile1");
+       extract("$tmpdir/$outfile", 12866, 5817, "$fwfile2");
+
+       "$fwfile1 $fwfile2"
+}
+
+sub it9137 {
     my $url = "http://kworld.server261.com/kworld/CD/ITE_TiVme/V1.00/";
     my $zipfile = "Driver_V10.323.1.0412.100412.zip";
     my $hash = "79b597dc648698ed6820845c0c9d0d37";
index d49c2ec72d12762ee01c2c9474bc573efb53c26a..d725c0dfe032f0692ab9de9a4358dfdcdd711f39 100644 (file)
@@ -439,41 +439,6 @@ Who:       Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
 
-What:  Support for driver specific ioctls in the pwc driver (everything
-       defined in media/pwc-ioctl.h)
-When:  3.3
-Why:   This stems from the v4l1 era, with v4l2 everything can be done with
-       standardized v4l2 API calls
-Who:   Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:  Driver specific sysfs API in the pwc driver
-When:  3.3
-Why:   Setting pan/tilt should be done with v4l2 controls, like with other
-       cams. The button is available as a standard input device
-Who:   Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:  Driver specific use of pixfmt.priv in the pwc driver
-When:  3.3
-Why:   The .priv field never was intended for this, setting a framerate is
-       support using the standardized S_PARM ioctl
-Who:   Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:  Software emulation of arbritary resolutions in the pwc driver
-When:  3.3
-Why:   The pwc driver claims to support any resolution between 160x120
-       and 640x480, but emulates this by simply drawing a black border
-       around the image. Userspace can draw its own black border if it
-       really wants one.
-Who:   Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
 What:  For VIDIOC_S_FREQUENCY the type field must match the device node's type.
        If not, return -EINVAL.
 When:  3.2
index 6f496a5867324cc5750f90ecd0fd91d3547b554d..23b7def21ba8bc5fe9e797e2b4cce1b94245d969 100644 (file)
@@ -26,6 +26,10 @@ Supported chips:
     Prefix: 'it8721'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
+  * IT8728F
+    Prefix: 'it8728'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * SiS950   [clone of IT8705F]
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -71,7 +75,7 @@ Description
 -----------
 
 This driver implements support for the IT8705F, IT8712F, IT8716F,
-IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips.
+IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips.
 
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -105,6 +109,9 @@ The IT8726F is just bit enhanced IT8716F with additional hardware
 for AMD power sequencing. Therefore the chip will appear as IT8716F
 to userspace applications.
 
+The IT8728F is considered compatible with the IT8721F, until a datasheet
+becomes available (hopefully.)
+
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
 
@@ -121,8 +128,8 @@ alarm is triggered if the voltage has crossed a programmable minimum or
 maximum limit. Note that minimum in this case always means 'closest to
 zero'; this is important for negative voltage measurements. All voltage
 inputs can measure voltages between 0 and 4.08 volts, with a resolution of
-0.016 volt (except IT8721F/IT8758E: 0.012 volt.) The battery voltage in8 does
-not have limit registers.
+0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
+voltage in8 does not have limit registers.
 
 On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
 the chip (in7, in8 and optionally in3). The driver handles this transparently
index b9843eab1afb107d6ffb13239b6df435bd7c8c54..4d30d209881a2861ad95c07208a7179ead236b03 100644 (file)
@@ -12,6 +12,11 @@ Supported chips:
     Addresses scanned: I2C 0x18 and 0x4e
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/pf/LM/LM64.html
+  * National Semiconductor LM96163
+    Prefix: 'lm96163'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM96163.html
 
 Author: Jean Delvare <khali@linux-fr.org>
 
@@ -49,16 +54,24 @@ value for measuring the speed of the fan. It can measure fan speeds down to
 Note that the pin used for fan monitoring is shared with an alert out
 function. Depending on how the board designer wanted to use the chip, fan
 speed monitoring will or will not be possible. The proper chip configuration
-is left to the BIOS, and the driver will blindly trust it.
+is left to the BIOS, and the driver will blindly trust it. Only the original
+LM63 suffers from this limitation, the LM64 and LM96163 have separate pins
+for fan monitoring and alert out. On the LM64, monitoring is always enabled;
+on the LM96163 it can be disabled.
 
 A PWM output can be used to control the speed of the fan. The LM63 has two
 PWM modes: manual and automatic. Automatic mode is not fully implemented yet
 (you cannot define your custom PWM/temperature curve), and mode change isn't
 supported either.
 
-The lm63 driver will not update its values more frequently than every
-second; reading them more often will do no harm, but will return 'old'
-values.
+The lm63 driver will not update its values more frequently than configured with
+the update_interval sysfs attribute; reading them more often will do no harm,
+but will return 'old' values. Values in the automatic fan control lookup table
+(attributes pwm1_auto_*) have their own independent lifetime of 5 seconds.
 
 The LM64 is effectively an LM63 with GPIO lines. The driver does not
 support these GPIO lines at present.
+
+The LM96163 is an enhanced version of LM63 with improved temperature accuracy
+and better PWM resolution. For LM96163, the external temperature sensor type is
+configurable as CPU embedded diode(1) or 3904 transistor(2).
index a4aa8f600e09643beb6a2b505c9c08d00f28166a..1f4dd855a299350ec707fc9ec34630baef29c689 100644 (file)
@@ -304,7 +304,7 @@ value (fastest fan speed) wins.
 temp[1-*]_type Sensor type selection.
                Integers 1 to 6
                RW
-               1: PII/Celeron Diode
+               1: CPU embedded diode
                2: 3904 transistor
                3: thermal diode
                4: thermistor
index f47cdefb4d1efc17d4e515df31996f134674649e..ab0a984530d87848435571d857b201484591f73c 100644 (file)
@@ -33,14 +33,15 @@ This document describes the Linux kernel Makefiles.
 
        === 6 Architecture Makefiles
           --- 6.1 Set variables to tweak the build to the architecture
-          --- 6.2 Add prerequisites to archprepare:
-          --- 6.3 List directories to visit when descending
-          --- 6.4 Architecture-specific boot images
-          --- 6.5 Building non-kbuild targets
-          --- 6.6 Commands useful for building a boot image
-          --- 6.7 Custom kbuild commands
-          --- 6.8 Preprocessing linker scripts
-          --- 6.9 Generic header files
+          --- 6.2 Add prerequisites to archheaders:
+          --- 6.3 Add prerequisites to archprepare:
+          --- 6.4 List directories to visit when descending
+          --- 6.5 Architecture-specific boot images
+          --- 6.6 Building non-kbuild targets
+          --- 6.7 Commands useful for building a boot image
+          --- 6.8 Custom kbuild commands
+          --- 6.9 Preprocessing linker scripts
+          --- 6.10 Generic header files
 
        === 7 Kbuild syntax for exported headers
                --- 7.1 header-y
@@ -252,7 +253,7 @@ more details, with real examples.
        This will create a library lib.a based on delay.o. For kbuild to
        actually recognize that there is a lib.a being built, the directory
        shall be listed in libs-y.
-       See also "6.3 List directories to visit when descending".
+       See also "6.4 List directories to visit when descending".
 
        Use of lib-y is normally restricted to lib/ and arch/*/lib.
 
@@ -974,7 +975,20 @@ When kbuild executes, the following steps are followed (roughly):
        $(KBUILD_ARFLAGS) set by the top level Makefile to "D" (deterministic
        mode) if this option is supported by $(AR).
 
---- 6.2 Add prerequisites to archprepare:
+--- 6.2 Add prerequisites to archheaders:
+
+       The archheaders: rule is used to generate header files that
+       may be installed into user space by "make header_install" or
+       "make headers_install_all".  In order to support
+       "make headers_install_all", this target has to be able to run
+       on an unconfigured tree, or a tree configured for another
+       architecture.
+
+       It is run before "make archprepare" when run on the
+       architecture itself.
+
+
+--- 6.3 Add prerequisites to archprepare:
 
        The archprepare: rule is used to list prerequisites that need to be
        built before starting to descend down in the subdirectories.
@@ -990,7 +1004,7 @@ When kbuild executes, the following steps are followed (roughly):
        generating offset header files.
 
 
---- 6.3 List directories to visit when descending
+--- 6.4 List directories to visit when descending
 
        An arch Makefile cooperates with the top Makefile to define variables
        which specify how to build the vmlinux file.  Note that there is no
@@ -1019,7 +1033,7 @@ When kbuild executes, the following steps are followed (roughly):
                drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/
 
 
---- 6.4 Architecture-specific boot images
+--- 6.5 Architecture-specific boot images
 
        An arch Makefile specifies goals that take the vmlinux file, compress
        it, wrap it in bootstrapping code, and copy the resulting files
@@ -1070,7 +1084,7 @@ When kbuild executes, the following steps are followed (roughly):
 
        When "make" is executed without arguments, bzImage will be built.
 
---- 6.5 Building non-kbuild targets
+--- 6.6 Building non-kbuild targets
 
     extra-y
 
@@ -1090,7 +1104,7 @@ When kbuild executes, the following steps are followed (roughly):
        shall be built, but shall not be linked as part of built-in.o.
 
 
---- 6.6 Commands useful for building a boot image
+--- 6.7 Commands useful for building a boot image
 
        Kbuild provides a few macros that are useful when building a
        boot image.
@@ -1112,7 +1126,7 @@ When kbuild executes, the following steps are followed (roughly):
        always be built.
        Assignments to $(targets) are without $(obj)/ prefix.
        if_changed may be used in conjunction with custom commands as
-       defined in 6.7 "Custom kbuild commands".
+       defined in 6.8 "Custom kbuild commands".
 
        Note: It is a typical mistake to forget the FORCE prerequisite.
        Another common pitfall is that whitespace is sometimes
@@ -1171,7 +1185,7 @@ When kbuild executes, the following steps are followed (roughly):
                $(obj)/%.dtb: $(src)/%.dts
                        $(call cmd,dtc)
 
---- 6.7 Custom kbuild commands
+--- 6.8 Custom kbuild commands
 
        When kbuild is executing with KBUILD_VERBOSE=0, then only a shorthand
        of a command is normally displayed.
@@ -1198,7 +1212,7 @@ When kbuild executes, the following steps are followed (roughly):
        will be displayed with "make KBUILD_VERBOSE=0".
 
 
---- 6.8 Preprocessing linker scripts
+--- 6.9 Preprocessing linker scripts
 
        When the vmlinux image is built, the linker script
        arch/$(ARCH)/kernel/vmlinux.lds is used.
@@ -1228,7 +1242,7 @@ When kbuild executes, the following steps are followed (roughly):
        The kbuild infrastructure for *lds file are used in several
        architecture-specific files.
 
---- 6.9 Generic header files
+--- 6.10 Generic header files
 
        The directory include/asm-generic contains the header files
        that may be shared between individual architectures.
index d5cb4ea287b21dff9086d1d43c77a1874c033931..7b59e953c4bfe8673b7d65314fe9e65feb3676ef 100644 (file)
@@ -1,5 +1,5 @@
   0 -> Unknown board                            (au0828)
-  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008]
+  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008,2040:7260,2040:7213]
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
   4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
index 4739d568430599002d61d163be47a4be9e7a9f23..b753906c71830b892d95b623c857a767ba885571 100644 (file)
@@ -71,7 +71,7 @@
  70 -> Prolink Pixelview PV-BT878P+ (Rev.4C,8E)
  71 -> Lifeview FlyVideo 98EZ (capture only) LR51          [1851:1851]
  72 -> Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM) [1554:4011]
- 73 -> Sensoray 311                                        [6000:0311]
+ 73 -> Sensoray 311/611                                    [6000:0311,6000:0611]
  74 -> RemoteVision MX (RV605)
  75 -> Powercolor MTV878/ MTV878R/ MTV878F
  76 -> Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP) [0e11:0079]
 157 -> Geovision GV-800(S) (master)                        [800a:763d]
 158 -> Geovision GV-800(S) (slave)                         [800b:763d,800c:763d,800d:763d]
 159 -> ProVideo PV183                                      [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540]
+160 -> Tongwei Video Technology TD-3116                    [f200:3116]
index 8910449d23a8e355cc1fc86dd400638224166fc4..23584d0c6a753fddd12f5ee3fbd213c8d78665db 100644 (file)
@@ -29,3 +29,6 @@
  28 -> LEADTEK WinFast PxTV1200                            [107d:6f22]
  29 -> GoTView X5 3D Hybrid                                [5654:2390]
  30 -> NetUP Dual DVB-T/C-CI RF                            [1b55:e2e4]
+ 31 -> Leadtek Winfast PxDVR3200 H XC4000                  [107d:6f39]
+ 32 -> MPX-885
+ 33 -> Mygica X8507                                        [14f1:8502]
index d9c0f119196d0f2ef15dc1f3a70e40fd46e3524b..eee18e6962b6c9ae54a830dbcf8ad14b54bc742b 100644 (file)
@@ -85,3 +85,5 @@
  84 -> Samsung SMT 7020 DVB-S                              [18ac:dc00,18ac:dccd]
  85 -> Twinhan VP-1027 DVB-S                               [1822:0023]
  86 -> TeVii S464 DVB-S/S2                                 [d464:9022]
+ 87 -> Leadtek WinFast DTV2000 H PLUS                      [107d:6f42]
+ 88 -> Leadtek WinFast DTV1800 H (XC4000)                  [107d:6f38]
index 4a7b3df6d8bd7695a0cee2417d3d849b43912345..e7be3ac49ead4d9c72fa64b9f259f8215f85cd29 100644 (file)
@@ -11,7 +11,7 @@
  10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
  11 -> Terratec Hybrid XS                       (em2880)
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
- 13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
+ 13 -> Terratec Prodigy XS                      (em2880)
  14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
  15 -> V-Gear PocketTV                          (em2800)
  16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b]
@@ -40,7 +40,7 @@
  39 -> KWorld PVRTV 300U                        (em2861)        [eb1a:e300]
  40 -> Plextor ConvertX PX-TV100U               (em2861)        [093b:a005]
  41 -> Kworld 350 U DVB-T                       (em2870)        [eb1a:e350]
- 42 -> Kworld 355 U DVB-T                       (em2870)        [eb1a:e355,eb1a:e357]
+ 42 -> Kworld 355 U DVB-T                       (em2870)        [eb1a:e355,eb1a:e357,eb1a:e359]
  43 -> Terratec Cinergy T XS                    (em2870)        [0ccd:0043]
  44 -> Terratec Cinergy T XS (MT2060)           (em2870)
  45 -> Pinnacle PCTV DVB-T                      (em2870)
@@ -64,7 +64,7 @@
  64 -> Easy Cap Capture DC-60                   (em2860)
  65 -> IO-DATA GV-MVP/SZ                        (em2820/em2840) [04bb:0515]
  66 -> Empire dual TV                           (em2880)
- 67 -> Terratec Grabby                          (em2860)        [0ccd:0096]
+ 67 -> Terratec Grabby                          (em2860)        [0ccd:0096,0ccd:10AF]
  68 -> Terratec AV350                           (em2860)        [0ccd:0084]
  69 -> KWorld ATSC 315U HDTV TV Box             (em2882)        [eb1a:a313]
  70 -> Evga inDtube                             (em2882)
@@ -76,3 +76,7 @@
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
  77 -> EM2874 Leadership ISDBT                  (em2874)
  78 -> PCTV nanoStick T2 290e                   (em28174)
+ 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad]
+ 80 -> PCTV DVB-S2 Stick (460e)                 (em28174)
+ 81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
+ 82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
index 7efae9bd73eda9445ce6db29c079a20510d53a49..e7ef38a19859964f922aef707ab4f254b9ab8a22 100644 (file)
 185 -> MagicPro ProHDTV Pro2 DMB-TH/Hybrid      [17de:d136]
 186 -> Beholder BeholdTV 501                    [5ace:5010]
 187 -> Beholder BeholdTV 503 FM                 [5ace:5030]
+188 -> Sensoray 811/911                         [6000:0811,6000:0911]
index 152bd7b781ca51b5ceded74bb121642c50f8783b..2205e8d55537ccaf69395eed7540ae46149cec9e 100644 (file)
@@ -7,3 +7,5 @@
   6 -> Hauppauge WinTV-HVR2200                             [0070:8901]
   7 -> Hauppauge WinTV-HVR2250                             [0070:8891,0070:8851]
   8 -> Hauppauge WinTV-HVR2250                             [0070:88A1]
+  9 -> Hauppauge WinTV-HVR2200                             [0070:8940]
+ 10 -> Hauppauge WinTV-HVR2200                             [0070:8953]
index b15e29f3112113416f238cb686047430caf17eeb..f2060f0dc02c055b0f380174aa99a140b1cb1615 100644 (file)
@@ -189,6 +189,7 @@ ov519               05a9:0511       Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Ca
 ov519          05a9:0518       Creative WebCam
 ov519          05a9:0519       OV519 Microphone
 ov519          05a9:0530       OmniVision
+ov534_9                05a9:1550       OmniVision VEHO Filmscanner
 ov519          05a9:2800       OmniVision SuperCAM
 ov519          05a9:4519       Webcam Classic
 ov534_9                05a9:8065       OmniVision test kit ov538+ov9712
@@ -278,6 +279,7 @@ pac7302             093a:2628       Genius iLook 300
 pac7302                093a:2629       Genious iSlim 300
 pac7302                093a:262a       Webcam 300k
 pac7302                093a:262c       Philips SPC 230 NC
+jl2005bcd      0979:0227       Various brands, 19 known cameras supported
 jeilinj                0979:0280       Sakar 57379
 jeilinj                0979:0280       Sportscam DV15
 zc3xx          0ac8:0302       Z-star Vimicro zc0302
index f8dcabf7852cfa1f26ef5103703083539e14f7ab..659b2ba12a4fd69297073c0e68c69ec992d83b1f 100644 (file)
@@ -612,6 +612,12 @@ You can set a pointer to a mutex_lock in struct video_device. Usually this
 will be either a top-level mutex or a mutex per device node. If you want
 finer-grained locking then you have to set it to NULL and do you own locking.
 
+It is up to the driver developer to decide which method to use. However, if
+your driver has high-latency operations (for example, changing the exposure
+of a USB webcam might take a long time), then you might be better off with
+doing your own locking if you want to allow the user to do other things with
+the device while waiting for the high-latency command to finish.
+
 If a lock is specified then all file operations will be serialized on that
 lock. If you use videobuf then you must pass the same lock to the videobuf
 queue initialize function: if videobuf has to wait for a frame to arrive, then
@@ -619,6 +625,11 @@ it will temporarily unlock the lock and relock it afterwards. If your driver
 also waits in the code, then you should do the same to allow other processes
 to access the device node while the first process is waiting for something.
 
+In the case of videobuf2 you will need to implement the wait_prepare and
+wait_finish callbacks to unlock/lock if applicable. In particular, if you use
+the lock in struct video_device then you must unlock/lock this mutex in
+wait_prepare and wait_finish.
+
 The implementation of a hotplug disconnect should also take the lock before
 calling v4l2_device_disconnect.
 
index ebbee877330f076f9eedf360bcfd8c103dc0636c..2a90101309d1b396a9f8417a52dd55256b333731 100644 (file)
@@ -2821,6 +2821,14 @@ L:       platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/fujitsu-laptop.c
 
+FUJITSU M-5MO LS CAMERA ISP DRIVER
+M:     Kyungmin Park <kyungmin.park@samsung.com>
+M:     Heungjun Kim <riverful.kim@samsung.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/video/m5mols/
+F:     include/media/m5mols.h
+
 FUSE: FILESYSTEM IN USERSPACE
 M:     Miklos Szeredi <miklos@szeredi.hu>
 L:     fuse-devel@lists.sourceforge.net
index adddd11c3b3b8a2827dc4f591b573b1fde5768a9..156ac69c961e8d0ec0b99649aae2d72a0e85c313 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -312,7 +312,7 @@ endif
 # If the user is running make -s (silent mode), suppress echoing of
 # commands
 
-ifneq ($(findstring s,$(MAKEFLAGS)),)
+ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
   quiet=silent_
 endif
 
@@ -442,7 +442,7 @@ asm-generic:
 
 no-dot-config-targets := clean mrproper distclean \
                         cscope gtags TAGS tags help %docs check% coccicheck \
-                        include/linux/version.h headers_% \
+                        include/linux/version.h headers_% archheaders \
                         kernelversion %src-pkg
 
 config-targets := 0
@@ -979,7 +979,7 @@ prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
                    include/config/auto.conf
        $(cmd_crmodverdir)
 
-archprepare: prepare1 scripts_basic
+archprepare: archheaders prepare1 scripts_basic
 
 prepare0: archprepare FORCE
        $(Q)$(MAKE) $(build)=.
@@ -1046,8 +1046,11 @@ hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
 # If we do an all arch process set dst to asm-$(hdr-arch)
 hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
 
+PHONY += archheaders
+archheaders:
+
 PHONY += __headers
-__headers: include/linux/version.h scripts_basic asm-generic FORCE
+__headers: include/linux/version.h scripts_basic asm-generic archheaders FORCE
        $(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
index 5df26a9976a26c10ddfcf0f788302dd2caeb8769..fc871e719aae8bd6e94d5602591f2948f568f8e9 100644 (file)
@@ -59,9 +59,11 @@ $(obj)/zImage:       $(obj)/compressed/vmlinux FORCE
 
 endif
 
+targets += $(dtb-y)
+
 # Rule to build device tree blobs
-$(obj)/%.dtb: $(src)/dts/%.dts
-       $(call cmd,dtc)
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+       $(call if_changed_dep,dtc)
 
 $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
 
index 7151753b0989f922c5a0e9d29fce5e057ae2ad5e..c402e9b31f4c61148ee5466b29f9ec176f11b78f 100644 (file)
@@ -2,7 +2,7 @@
 #define _ARCH_ARM_GPIO_H
 
 #if CONFIG_ARCH_NR_GPIO > 0
-#define ARCH_NR_GPIO CONFIG_ARCH_NR_GPIO
+#define ARCH_NR_GPIOS CONFIG_ARCH_NR_GPIO
 #endif
 
 /* not all ARM platforms necessarily support this API ... */
index b8da2e415e4eb21a870cbb52333b5400a50ad163..00ca5f92648ea56616afe8bfbd4a25ff8f0b0e27 100644 (file)
@@ -6,4 +6,6 @@ struct machine_desc;
 
 extern void arm_memblock_init(struct meminfo *, struct machine_desc *);
 
+phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align);
+
 #endif
index 14e277d2ff911ec7690c4223c5acea4b602e3450..6d579114406673fd1b97c09f0cdcbb7263b044da 100644 (file)
@@ -99,6 +99,14 @@ ENTRY(stext)
  THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_p                       @ yes, error 'p'
 
+#ifdef CONFIG_ARM_LPAE
+       mrc     p15, 0, r3, c0, c1, 4           @ read ID_MMFR0
+       and     r3, r3, #0xf                    @ extract VMSA support
+       cmp     r3, #5                          @ long-descriptor translation table format?
+ THUMB( it     lo )                            @ force fixup-able long branch encoding
+       blo     __error_p                       @ only classic page table format
+#endif
+
 #ifndef CONFIG_XIP_KERNEL
        adr     r3, 2f
        ldmia   r3, {r4, r8}
index 89c33258639f89a9b075a2f9bf6ca0bf41b7a0e8..4d1aab154400fb43e4e0de2ea38e49c932d278e0 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/3ds_debugboard.h>
@@ -754,10 +755,8 @@ static struct sys_timer mx31_3ds_timer = {
 static void __init mx31_3ds_reserve(void)
 {
        /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX31_3DS_CAMERA_BUF_SIZE,
                                         MX31_3DS_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
index b95981dacb2bcef2ff8138b59d32f58d85d3a394..f225262b5c38551cb6ec424e01cb71139f9a551f 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/board-mx31moboard.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -584,10 +585,8 @@ struct sys_timer mx31moboard_timer = {
 static void __init mx31moboard_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
                        MX3_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
index d7e151669ed347591e1687de4c628156aa56820d..e48854b9d9907a7c76095b5531c3a9f63eb0db23 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
@@ -680,10 +681,8 @@ struct sys_timer pcm037_timer = {
 static void __init pcm037_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
                        MX3_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
index 904bd1dfcd2e26b194f24ebe62eee9a377a05016..a8ba7b96dcd1c3177b11e634e5e8e4608dc7a4d4 100644 (file)
@@ -366,8 +366,8 @@ config OMAP3_SDRC_AC_TIMING
          going on could result in system crashes;
 
 config OMAP4_ERRATA_I688
-       bool "OMAP4 errata: Async Bridge Corruption"
-       depends on ARCH_OMAP4
+       bool "OMAP4 errata: Async Bridge Corruption (BROKEN)"
+       depends on ARCH_OMAP4 && BROKEN
        select ARCH_HAS_BARRIERS
        help
          If a data is stalled inside asynchronous bridge because of back
index 46dfd1ae8f71a6001f90ecdcea237103f906dcc4..0b510ad01a00b5a7ad4ae224f17447e8bba6301f 100644 (file)
@@ -28,7 +28,6 @@
 #include <plat/board.h>
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
-#include <plat/iommu.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -128,6 +127,10 @@ static struct platform_device omap2cam_device = {
 };
 #endif
 
+#if defined(CONFIG_IOMMU_API)
+
+#include <plat/iommu.h>
+
 static struct resource omap3isp_resources[] = {
        {
                .start          = OMAP3430_ISP_BASE,
@@ -224,6 +227,15 @@ int omap3_init_camera(struct isp_platform_data *pdata)
        return platform_device_register(&omap3isp_device);
 }
 
+#else /* !CONFIG_IOMMU_API */
+
+int omap3_init_camera(struct isp_platform_data *pdata)
+{
+       return 0;
+}
+
+#endif
+
 static inline void omap_init_camera(void)
 {
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
index 69f3c72d959b61e6cefe7c62462fc30f05a0b15f..d8f8ef40290f4dc4c803e69ce87fe5111baed499 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/memblock.h>
 
 #include <asm/cacheflush.h>
+#include <asm/memblock.h>
 
 #include <mach/omap-secure.h>
 
@@ -57,20 +58,10 @@ u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
 /* Allocate the memory to save secure ram */
 int __init omap_secure_ram_reserve_memblock(void)
 {
-       phys_addr_t paddr;
        u32 size = OMAP_SECURE_RAM_STORAGE;
 
        size = ALIGN(size, SZ_1M);
-       paddr = memblock_alloc(size, SZ_1M);
-       if (!paddr) {
-               pr_err("%s: failed to reserve %x bytes\n",
-                               __func__, size);
-               return -ENOMEM;
-       }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
-
-       omap_secure_memblock_base = paddr;
+       omap_secure_memblock_base = arm_memblock_steal(size, SZ_1M);
 
        return 0;
 }
index bc16c818c6b72e77ae276976c887b7a85647a9df..40a8fbc07e4b766717b35e8b69f88794c1335df7 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 
 #include <plat/irqs.h>
 #include <plat/sram.h>
@@ -61,13 +62,8 @@ static int __init omap_barriers_init(void)
                return -ENODEV;
 
        size = ALIGN(PAGE_SIZE, SZ_1M);
-       paddr = memblock_alloc(size, SZ_1M);
-       if (!paddr) {
-               pr_err("%s: failed to reserve 4 Kbytes\n", __func__);
-               return -ENOMEM;
-       }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
+       paddr = arm_memblock_steal(size, SZ_1M);
+
        dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
        dram_io_desc[0].pfn = __phys_to_pfn(paddr);
        dram_io_desc[0].length = size;
index 5bc6b3837b2033cbaccf57b69b91e07ffd0fe76f..ebafe8aa8956e1d9f7e24987e777ce7d87f27369 100644 (file)
@@ -280,7 +280,7 @@ static void __init map_sa1100_gpio_regs( void )
        int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
        pmd_t *pmd;
 
-       pmd = pmd_offset(pgd_offset_k(virt), virt);
+       pmd = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt);
        *pmd = __pmd(phys | prot);
        flush_pmd_entry(pmd);
 }
index 77b8fc12fc2f1ab0000ae734fff09624ba7cbf44..fcf8b1761aef723c6f3e5f3bd1f2b42cf436e04a 100644 (file)
@@ -276,7 +276,7 @@ static int sh7372_a3sp_suspend(void)
         * Serial consoles make use of SCIF hardware located in A3SP,
         * keep such power domain on if "no_console_suspend" is set.
         */
-       return console_suspend_enabled ? -EBUSY : 0;
+       return console_suspend_enabled ? 0 : -EBUSY;
 }
 
 struct sh7372_pm_domain sh7372_a3sp = {
index 3de4a5211c3b1702ac0aa1fb126c4b69f6e918c4..06d867dce55161df7d0ab34dfd11d0027e64795c 100644 (file)
@@ -48,7 +48,7 @@ static void clock_source_select(const char *dev_id, unsigned int clkval)
                offset = ATAOFFSET;
        else if (strcmp(dev_id, "nuc900-lcd") == 0)
                offset = LCDOFFSET;
-       else if (strcmp(dev_id, "nuc900-audio") == 0)
+       else if (strcmp(dev_id, "nuc900-ac97") == 0)
                offset = AUDOFFSET;
        else
                offset = CPUOFFSET;
index 604e1db266e8402d5f85c018c3870e15794c8bef..9a06619929090c43dd4993bfeeb3878319ac901b 100644 (file)
@@ -79,7 +79,7 @@ static DEFINE_CLK(timer4, 23);
 
 static struct clk_lookup nuc900_clkregs[] = {
        DEF_CLKLOOK(&clk_lcd, "nuc900-lcd", NULL),
-       DEF_CLKLOOK(&clk_audio, "nuc900-audio", NULL),
+       DEF_CLKLOOK(&clk_audio, "nuc900-ac97", NULL),
        DEF_CLKLOOK(&clk_fmi, "nuc900-fmi", NULL),
        DEF_CLKLOOK(&clk_ms, "nuc900-fmi", "MS"),
        DEF_CLKLOOK(&clk_sd, "nuc900-fmi", "SD"),
index 5b0c38abacc107a7eae8bd35ec8f03666f3422e7..78110befb7a9132d6da3353fdec6721b421894ed 100644 (file)
@@ -501,8 +501,8 @@ static struct resource nuc900_ac97_resource[] = {
 
 };
 
-struct platform_device nuc900_device_audio = {
-       .name           = "nuc900-audio",
+struct platform_device nuc900_device_ac97 = {
+       .name           = "nuc900-ac97",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(nuc900_ac97_resource),
        .resource       = nuc900_ac97_resource,
@@ -523,7 +523,7 @@ static struct platform_device *nuc900_public_dev[] __initdata = {
        &nuc900_device_emc,
        &nuc900_device_spi,
        &nuc900_device_wdt,
-       &nuc900_device_audio,
+       &nuc900_device_ac97,
 };
 
 /* Provide adding specific CPU platform devices API */
index 9dd74612bb8707560abd06e6adc250f7ecd54bf2..c58d142b8a467134d193d2252ce52a361e314fcf 100644 (file)
@@ -155,7 +155,7 @@ void mfp_set_groupg(struct device *dev, const char *subname)
        } else if (strcmp(dev_id, "nuc900-i2c1") == 0) {
                mfpen &= ~(GPIOG2TO3);
                mfpen |= ENI2C1;/*enable i2c1*/
-       } else if (strcmp(dev_id, "nuc900-audio") == 0) {
+       } else if (strcmp(dev_id, "nuc900-ac97") == 0) {
                mfpen &= ~(GPIOG22TO23);
                mfpen |= ENAC97;/*enable AC97*/
        } else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
index e34ea8adc1f928fe8ebeadc677aba06fbd8b4f47..6ec1226fc62d2fc58caa6c795614455c0f7e8ed7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/memblock.h>
 
 #include <asm/mach-types.h>
+#include <asm/memblock.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -307,6 +308,21 @@ static void arm_memory_present(void)
 }
 #endif
 
+static bool arm_memblock_steal_permitted = true;
+
+phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+{
+       phys_addr_t phys;
+
+       BUG_ON(!arm_memblock_steal_permitted);
+
+       phys = memblock_alloc(size, align);
+       memblock_free(phys, size);
+       memblock_remove(phys, size);
+
+       return phys;
+}
+
 void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 {
        int i;
@@ -349,6 +365,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
        if (mdesc->reserve)
                mdesc->reserve();
 
+       arm_memblock_steal_permitted = false;
        memblock_allow_resize();
        memblock_dump_all();
 }
index 19719329a47b0fb96a4b75e42f8103f505c00c84..60278f47c0bdd71953cc5c1483a68a7a02a0b50f 100644 (file)
@@ -20,6 +20,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 
 #include <plat/tc.h>
 #include <plat/board.h>
@@ -164,14 +165,12 @@ void __init omap_dsp_reserve_sdram_memblock(void)
        if (!size)
                return;
 
-       paddr = memblock_alloc(size, SZ_1M);
+       paddr = arm_memblock_steal(size, SZ_1M);
        if (!paddr) {
                pr_err("%s: failed to reserve %x bytes\n",
                                __func__, size);
                return;
        }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
 
        omap_dsp_phys_mempool_base = paddr;
 }
index 1121df13e15f52de91d7d30ee41399950e60ee72..21f1fda8b661ee7021782921b98b6cb637547284 100644 (file)
@@ -38,8 +38,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/system-reset.h>
-
 #include <mach/regs-gpio.h>
 #include <plat/regs-serial.h>
 
index 4c4e58ef0cb628ed3ca0f542536872036f93da02..0c796cf8158629abf23adb530c17ba2a8ceb9be5 100644 (file)
@@ -53,6 +53,6 @@ $(obj)/simpleImage.%: vmlinux FORCE
 DTC_FLAGS := -p 1024
 
 $(obj)/%.dtb: $(src)/dts/%.dts FORCE
-       $(call cmd,dtc)
+       $(call if_changed_dep,dtc)
 
 clean-files += *.dtb simpleImage.*.unstrip linux.bin.ub
index 604cd9dd133362712e5220510be83be134d96ec1..d4fc1a9717796610623cefa50c0ffd706225087e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/cache.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
+#include <linux/cpu.h>
 #include <asm/cacheflush.h>
 #include <asm/entry.h>
 #include <asm/cpuinfo.h>
@@ -226,5 +227,23 @@ static int __init setup_bus_notifier(void)
 
        return 0;
 }
-
 arch_initcall(setup_bus_notifier);
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+       int i, ret;
+
+       for_each_present_cpu(i) {
+               struct cpu *c = &per_cpu(cpu_devices, i);
+
+               ret = register_cpu(c, i);
+               if (ret)
+                       printk(KERN_WARNING "topology_init: register_cpu %d "
+                                               "failed (%d)\n", i, ret);
+       }
+
+       return 0;
+}
+subsys_initcall(topology_init);
index 98ca185097a519bb4bc58938ee848234e81db3b4..09958358601a3637ec4d811826b3f84fea1a6f96 100644 (file)
@@ -11,5 +11,5 @@ clean-files := *.dtb.S
 
 #DTC_FLAGS ?= -p 1024
 
-$(obj)/%.dtb: $(src)/dts/%.dts
-       $(call cmd,dtc)
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+       $(call if_changed_dep,dtc)
index 15986e70799ccbcb78d7aafc924d01bcf167a7a9..8844a17ce8ede20213d2c64d25d0d764587e834e 100644 (file)
@@ -345,8 +345,8 @@ $(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
        $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
 
 # Rule to build device tree blobs
-$(obj)/%.dtb: $(src)/dts/%.dts
-       $(call cmd,dtc)
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+       $(call if_changed_dep,dtc)
 
 # If there isn't a platform selected then just strip the vmlinux.
 ifeq (,$(image-y))
index 7730af6ec13feba4898ca3a8e85e3e416c57c33d..28688e6d96d795c3f860f5343524584b0cefb994 100644 (file)
@@ -64,7 +64,8 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
 #This will adjust *FLAGS accordingly to the platform.
 include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 
-KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include \
+                  -I$(HOST_DIR)/include/generated
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -96,6 +97,10 @@ endef
 
 KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig
 
+archheaders:
+       $(Q)$(MAKE) -C '$(srctree)' KBUILD_SRC= \
+               ARCH=$(SUBARCH) O='$(objtree)' archheaders
+
 archprepare: include/generated/user_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
@@ -135,7 +140,7 @@ archclean:
 
 # Generated files
 
-$(HOST_DIR)/um/user-offsets.s: FORCE
+$(HOST_DIR)/um/user-offsets.s: __headers FORCE
        $(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@
 
 define filechk_gen-asm-offsets
index b02e509072a790b1fbea3387f8749b5326beb822..209ba1294592c406bd735df889f43f6272acbddb 100644 (file)
@@ -117,6 +117,12 @@ KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
 
+###
+# Syscall table generation
+
+archheaders:
+       $(Q)$(MAKE) $(build)=arch/x86/syscalls all
+
 ###
 # Kernel objects
 
index 52d0ccfcf6eafbc84fe0d66270b165b34101639d..455646e0e53282ad97721c4c04420de09e36f3d2 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o
+obj-$(CONFIG_IA32_EMULATION) += nosyscall.o syscall_ia32.o
 
 sysv-$(CONFIG_SYSVIPC) := ipc32.o
 obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
index 3e274564f6bf0d89f06b489484eb7d86faa049d6..1106261856c8022610bface1d874c38f24b9bf63 100644 (file)
@@ -27,8 +27,6 @@
 
        .section .entry.text, "ax"
 
-#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
-
        .macro IA32_ARG_FIXUP noebp=0
        movl    %edi,%r8d
        .if \noebp
@@ -447,9 +445,6 @@ ia32_badsys:
        movq $-ENOSYS,%rax
        jmp ia32_sysret
 
-quiet_ni_syscall:
-       movq $-ENOSYS,%rax
-       ret
        CFI_ENDPROC
        
        .macro PTREGSCALL label, func, arg
@@ -494,357 +489,3 @@ ia32_ptregs_common:
        jmp  ia32_sysret        /* misbalances the return cache */
        CFI_ENDPROC
 END(ia32_ptregs_common)
-
-       .section .rodata,"a"
-       .align 8
-ia32_sys_call_table:
-       .quad sys_restart_syscall
-       .quad sys_exit
-       .quad stub32_fork
-       .quad sys_read
-       .quad sys_write
-       .quad compat_sys_open           /* 5 */
-       .quad sys_close
-       .quad sys32_waitpid
-       .quad sys_creat
-       .quad sys_link
-       .quad sys_unlink                /* 10 */
-       .quad stub32_execve
-       .quad sys_chdir
-       .quad compat_sys_time
-       .quad sys_mknod
-       .quad sys_chmod         /* 15 */
-       .quad sys_lchown16
-       .quad quiet_ni_syscall                  /* old break syscall holder */
-       .quad sys_stat
-       .quad sys32_lseek
-       .quad sys_getpid                /* 20 */
-       .quad compat_sys_mount  /* mount  */
-       .quad sys_oldumount     /* old_umount  */
-       .quad sys_setuid16
-       .quad sys_getuid16
-       .quad compat_sys_stime  /* stime */             /* 25 */
-       .quad compat_sys_ptrace /* ptrace */
-       .quad sys_alarm
-       .quad sys_fstat /* (old)fstat */
-       .quad sys_pause
-       .quad compat_sys_utime  /* 30 */
-       .quad quiet_ni_syscall  /* old stty syscall holder */
-       .quad quiet_ni_syscall  /* old gtty syscall holder */
-       .quad sys_access
-       .quad sys_nice  
-       .quad quiet_ni_syscall  /* 35 */        /* old ftime syscall holder */
-       .quad sys_sync
-       .quad sys32_kill
-       .quad sys_rename
-       .quad sys_mkdir
-       .quad sys_rmdir         /* 40 */
-       .quad sys_dup
-       .quad sys_pipe
-       .quad compat_sys_times
-       .quad quiet_ni_syscall                  /* old prof syscall holder */
-       .quad sys_brk           /* 45 */
-       .quad sys_setgid16
-       .quad sys_getgid16
-       .quad sys_signal
-       .quad sys_geteuid16
-       .quad sys_getegid16     /* 50 */
-       .quad sys_acct
-       .quad sys_umount                        /* new_umount */
-       .quad quiet_ni_syscall                  /* old lock syscall holder */
-       .quad compat_sys_ioctl
-       .quad compat_sys_fcntl64                /* 55 */
-       .quad quiet_ni_syscall                  /* old mpx syscall holder */
-       .quad sys_setpgid
-       .quad quiet_ni_syscall                  /* old ulimit syscall holder */
-       .quad sys_olduname
-       .quad sys_umask         /* 60 */
-       .quad sys_chroot
-       .quad compat_sys_ustat
-       .quad sys_dup2
-       .quad sys_getppid
-       .quad sys_getpgrp               /* 65 */
-       .quad sys_setsid
-       .quad sys32_sigaction
-       .quad sys_sgetmask
-       .quad sys_ssetmask
-       .quad sys_setreuid16    /* 70 */
-       .quad sys_setregid16
-       .quad sys32_sigsuspend
-       .quad compat_sys_sigpending
-       .quad sys_sethostname
-       .quad compat_sys_setrlimit      /* 75 */
-       .quad compat_sys_old_getrlimit  /* old_getrlimit */
-       .quad compat_sys_getrusage
-       .quad compat_sys_gettimeofday
-       .quad compat_sys_settimeofday
-       .quad sys_getgroups16   /* 80 */
-       .quad sys_setgroups16
-       .quad compat_sys_old_select
-       .quad sys_symlink
-       .quad sys_lstat
-       .quad sys_readlink              /* 85 */
-       .quad sys_uselib
-       .quad sys_swapon
-       .quad sys_reboot
-       .quad compat_sys_old_readdir
-       .quad sys32_mmap                /* 90 */
-       .quad sys_munmap
-       .quad sys_truncate
-       .quad sys_ftruncate
-       .quad sys_fchmod
-       .quad sys_fchown16              /* 95 */
-       .quad sys_getpriority
-       .quad sys_setpriority
-       .quad quiet_ni_syscall                  /* old profil syscall holder */
-       .quad compat_sys_statfs
-       .quad compat_sys_fstatfs                /* 100 */
-       .quad sys_ioperm
-       .quad compat_sys_socketcall
-       .quad sys_syslog
-       .quad compat_sys_setitimer
-       .quad compat_sys_getitimer      /* 105 */
-       .quad compat_sys_newstat
-       .quad compat_sys_newlstat
-       .quad compat_sys_newfstat
-       .quad sys_uname
-       .quad stub32_iopl               /* 110 */
-       .quad sys_vhangup
-       .quad quiet_ni_syscall  /* old "idle" system call */
-       .quad sys32_vm86_warning        /* vm86old */ 
-       .quad compat_sys_wait4
-       .quad sys_swapoff               /* 115 */
-       .quad compat_sys_sysinfo
-       .quad sys32_ipc
-       .quad sys_fsync
-       .quad stub32_sigreturn
-       .quad stub32_clone              /* 120 */
-       .quad sys_setdomainname
-       .quad sys_newuname
-       .quad sys_modify_ldt
-       .quad compat_sys_adjtimex
-       .quad sys32_mprotect            /* 125 */
-       .quad compat_sys_sigprocmask
-       .quad quiet_ni_syscall          /* create_module */
-       .quad sys_init_module
-       .quad sys_delete_module
-       .quad quiet_ni_syscall          /* 130  get_kernel_syms */
-       .quad sys32_quotactl
-       .quad sys_getpgid
-       .quad sys_fchdir
-       .quad quiet_ni_syscall  /* bdflush */
-       .quad sys_sysfs         /* 135 */
-       .quad sys_personality
-       .quad quiet_ni_syscall  /* for afs_syscall */
-       .quad sys_setfsuid16
-       .quad sys_setfsgid16
-       .quad sys_llseek                /* 140 */
-       .quad compat_sys_getdents
-       .quad compat_sys_select
-       .quad sys_flock
-       .quad sys_msync
-       .quad compat_sys_readv          /* 145 */
-       .quad compat_sys_writev
-       .quad sys_getsid
-       .quad sys_fdatasync
-       .quad compat_sys_sysctl /* sysctl */
-       .quad sys_mlock         /* 150 */
-       .quad sys_munlock
-       .quad sys_mlockall
-       .quad sys_munlockall
-       .quad sys_sched_setparam
-       .quad sys_sched_getparam   /* 155 */
-       .quad sys_sched_setscheduler
-       .quad sys_sched_getscheduler
-       .quad sys_sched_yield
-       .quad sys_sched_get_priority_max
-       .quad sys_sched_get_priority_min  /* 160 */
-       .quad sys32_sched_rr_get_interval
-       .quad compat_sys_nanosleep
-       .quad sys_mremap
-       .quad sys_setresuid16
-       .quad sys_getresuid16   /* 165 */
-       .quad sys32_vm86_warning        /* vm86 */ 
-       .quad quiet_ni_syscall  /* query_module */
-       .quad sys_poll
-       .quad quiet_ni_syscall /* old nfsservctl */
-       .quad sys_setresgid16   /* 170 */
-       .quad sys_getresgid16
-       .quad sys_prctl
-       .quad stub32_rt_sigreturn
-       .quad sys32_rt_sigaction
-       .quad sys32_rt_sigprocmask      /* 175 */
-       .quad sys32_rt_sigpending
-       .quad compat_sys_rt_sigtimedwait
-       .quad sys32_rt_sigqueueinfo
-       .quad sys_rt_sigsuspend
-       .quad sys32_pread               /* 180 */
-       .quad sys32_pwrite
-       .quad sys_chown16
-       .quad sys_getcwd
-       .quad sys_capget
-       .quad sys_capset
-       .quad stub32_sigaltstack
-       .quad sys32_sendfile
-       .quad quiet_ni_syscall          /* streams1 */
-       .quad quiet_ni_syscall          /* streams2 */
-       .quad stub32_vfork            /* 190 */
-       .quad compat_sys_getrlimit
-       .quad sys_mmap_pgoff
-       .quad sys32_truncate64
-       .quad sys32_ftruncate64
-       .quad sys32_stat64              /* 195 */
-       .quad sys32_lstat64
-       .quad sys32_fstat64
-       .quad sys_lchown
-       .quad sys_getuid
-       .quad sys_getgid                /* 200 */
-       .quad sys_geteuid
-       .quad sys_getegid
-       .quad sys_setreuid
-       .quad sys_setregid
-       .quad sys_getgroups     /* 205 */
-       .quad sys_setgroups
-       .quad sys_fchown
-       .quad sys_setresuid
-       .quad sys_getresuid
-       .quad sys_setresgid     /* 210 */
-       .quad sys_getresgid
-       .quad sys_chown
-       .quad sys_setuid
-       .quad sys_setgid
-       .quad sys_setfsuid              /* 215 */
-       .quad sys_setfsgid
-       .quad sys_pivot_root
-       .quad sys_mincore
-       .quad sys_madvise
-       .quad compat_sys_getdents64     /* 220 getdents64 */
-       .quad compat_sys_fcntl64        
-       .quad quiet_ni_syscall          /* tux */
-       .quad quiet_ni_syscall          /* security */
-       .quad sys_gettid        
-       .quad sys32_readahead   /* 225 */
-       .quad sys_setxattr
-       .quad sys_lsetxattr
-       .quad sys_fsetxattr
-       .quad sys_getxattr
-       .quad sys_lgetxattr     /* 230 */
-       .quad sys_fgetxattr
-       .quad sys_listxattr
-       .quad sys_llistxattr
-       .quad sys_flistxattr
-       .quad sys_removexattr   /* 235 */
-       .quad sys_lremovexattr
-       .quad sys_fremovexattr
-       .quad sys_tkill
-       .quad sys_sendfile64 
-       .quad compat_sys_futex          /* 240 */
-       .quad compat_sys_sched_setaffinity
-       .quad compat_sys_sched_getaffinity
-       .quad sys_set_thread_area
-       .quad sys_get_thread_area
-       .quad compat_sys_io_setup       /* 245 */
-       .quad sys_io_destroy
-       .quad compat_sys_io_getevents
-       .quad compat_sys_io_submit
-       .quad sys_io_cancel
-       .quad sys32_fadvise64           /* 250 */
-       .quad quiet_ni_syscall  /* free_huge_pages */
-       .quad sys_exit_group
-       .quad sys32_lookup_dcookie
-       .quad sys_epoll_create
-       .quad sys_epoll_ctl             /* 255 */
-       .quad sys_epoll_wait
-       .quad sys_remap_file_pages
-       .quad sys_set_tid_address
-       .quad compat_sys_timer_create
-       .quad compat_sys_timer_settime  /* 260 */
-       .quad compat_sys_timer_gettime
-       .quad sys_timer_getoverrun
-       .quad sys_timer_delete
-       .quad compat_sys_clock_settime
-       .quad compat_sys_clock_gettime  /* 265 */
-       .quad compat_sys_clock_getres
-       .quad compat_sys_clock_nanosleep
-       .quad compat_sys_statfs64
-       .quad compat_sys_fstatfs64
-       .quad sys_tgkill                /* 270 */
-       .quad compat_sys_utimes
-       .quad sys32_fadvise64_64
-       .quad quiet_ni_syscall  /* sys_vserver */
-       .quad sys_mbind
-       .quad compat_sys_get_mempolicy  /* 275 */
-       .quad sys_set_mempolicy
-       .quad compat_sys_mq_open
-       .quad sys_mq_unlink
-       .quad compat_sys_mq_timedsend
-       .quad compat_sys_mq_timedreceive        /* 280 */
-       .quad compat_sys_mq_notify
-       .quad compat_sys_mq_getsetattr
-       .quad compat_sys_kexec_load     /* reserved for kexec */
-       .quad compat_sys_waitid
-       .quad quiet_ni_syscall          /* 285: sys_altroot */
-       .quad sys_add_key
-       .quad sys_request_key
-       .quad sys_keyctl
-       .quad sys_ioprio_set
-       .quad sys_ioprio_get            /* 290 */
-       .quad sys_inotify_init
-       .quad sys_inotify_add_watch
-       .quad sys_inotify_rm_watch
-       .quad sys_migrate_pages
-       .quad compat_sys_openat         /* 295 */
-       .quad sys_mkdirat
-       .quad sys_mknodat
-       .quad sys_fchownat
-       .quad compat_sys_futimesat
-       .quad sys32_fstatat             /* 300 */
-       .quad sys_unlinkat
-       .quad sys_renameat
-       .quad sys_linkat
-       .quad sys_symlinkat
-       .quad sys_readlinkat            /* 305 */
-       .quad sys_fchmodat
-       .quad sys_faccessat
-       .quad compat_sys_pselect6
-       .quad compat_sys_ppoll
-       .quad sys_unshare               /* 310 */
-       .quad compat_sys_set_robust_list
-       .quad compat_sys_get_robust_list
-       .quad sys_splice
-       .quad sys32_sync_file_range
-       .quad sys_tee                   /* 315 */
-       .quad compat_sys_vmsplice
-       .quad compat_sys_move_pages
-       .quad sys_getcpu
-       .quad sys_epoll_pwait
-       .quad compat_sys_utimensat      /* 320 */
-       .quad compat_sys_signalfd
-       .quad sys_timerfd_create
-       .quad sys_eventfd
-       .quad sys32_fallocate
-       .quad compat_sys_timerfd_settime        /* 325 */
-       .quad compat_sys_timerfd_gettime
-       .quad compat_sys_signalfd4
-       .quad sys_eventfd2
-       .quad sys_epoll_create1
-       .quad sys_dup3                          /* 330 */
-       .quad sys_pipe2
-       .quad sys_inotify_init1
-       .quad compat_sys_preadv
-       .quad compat_sys_pwritev
-       .quad compat_sys_rt_tgsigqueueinfo      /* 335 */
-       .quad sys_perf_event_open
-       .quad compat_sys_recvmmsg
-       .quad sys_fanotify_init
-       .quad sys32_fanotify_mark
-       .quad sys_prlimit64             /* 340 */
-       .quad sys_name_to_handle_at
-       .quad compat_sys_open_by_handle_at
-       .quad compat_sys_clock_adjtime
-       .quad sys_syncfs
-       .quad compat_sys_sendmmsg       /* 345 */
-       .quad sys_setns
-       .quad compat_sys_process_vm_readv
-       .quad compat_sys_process_vm_writev
-ia32_syscall_end:
diff --git a/arch/x86/ia32/nosyscall.c b/arch/x86/ia32/nosyscall.c
new file mode 100644 (file)
index 0000000..51ecd5b
--- /dev/null
@@ -0,0 +1,7 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+long compat_ni_syscall(void)
+{
+       return -ENOSYS;
+}
diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c
new file mode 100644 (file)
index 0000000..4754ba0
--- /dev/null
@@ -0,0 +1,25 @@
+/* System call table for ia32 emulation. */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+#include <asm/asm-offsets.h>
+
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void compat(void) ;
+#include <asm/syscalls_32.h>
+#undef __SYSCALL_I386
+
+#define __SYSCALL_I386(nr, sym, compat) [nr] = compat,
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void compat_ni_syscall(void);
+
+const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
+       /*
+        * Smells like a compiler bug -- it doesn't work
+        * when the & below is removed.
+        */
+       [0 ... __NR_ia32_syscall_max] = &compat_ni_syscall,
+#include <asm/syscalls_32.h>
+};
index 6fa90a845e4ca9aa741034195f6a7026077bcadc..b57e6a43a37a1f9ebca3f4a4966f54b31753e605 100644 (file)
@@ -19,7 +19,8 @@ header-y += processor-flags.h
 header-y += ptrace-abi.h
 header-y += sigcontext32.h
 header-y += ucontext.h
-header-y += unistd_32.h
-header-y += unistd_64.h
 header-y += vm86.h
 header-y += vsyscall.h
+
+genhdr-y += unistd_32.h
+genhdr-y += unistd_64.h
index 976f6ecd2ce691da49d58e433f0b76b0348622b2..b0d5716ca1e4b6fd76b232554e7778c60d5c89c3 100644 (file)
@@ -2,17 +2,10 @@
 #define _ASM_X86_IA32_UNISTD_H
 
 /*
- * This file contains the system call numbers of the ia32 port,
+ * This file contains the system call numbers of the ia32 compat ABI,
  * this is for the kernel only.
- * Only add syscalls here where some part of the kernel needs to know
- * the number. This should be otherwise in sync with asm-x86/unistd_32.h. -AK
  */
-
-#define __NR_ia32_restart_syscall 0
-#define __NR_ia32_exit           1
-#define __NR_ia32_read           3
-#define __NR_ia32_write                  4
-#define __NR_ia32_sigreturn    119
-#define __NR_ia32_rt_sigreturn 173
+#define __SYSCALL_ia32_NR(x) (x)
+#include <asm/unistd_32_ia32.h>
 
 #endif /* _ASM_X86_IA32_UNISTD_H */
index f35ce43c1a7785bd0d555f0b3f6a65ab417bba3b..6aefb14cbbc5d9c40dcbf89322a5d4a77103b48e 100644 (file)
@@ -151,7 +151,7 @@ static inline void enable_p5_mce(void) {}
 
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
-DECLARE_PER_CPU(struct device, mce_device);
+extern struct device *mce_device[CONFIG_NR_CPUS];
 
 /*
  * Maximum banks number.
index c4a348f7bd43de3932f88d0f8ddb5b66a7526863..d962e5652a7352498bd9654315f7819fb7d9d86b 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/sched.h>
 #include <linux/err.h>
+#include <asm/asm-offsets.h>   /* For NR_syscalls */
 
 extern const unsigned long sys_call_table[];
 
index 2a58ed3e51d8265627e185d5d8be3783c5ea9bf4..b4a3db7ce1408213e0def655e775ff3aa94c82c0 100644 (file)
@@ -1,13 +1,59 @@
+#ifndef _ASM_X86_UNISTD_H
+#define _ASM_X86_UNISTD_H 1
+
 #ifdef __KERNEL__
 # ifdef CONFIG_X86_32
-#  include "unistd_32.h"
+
+#  include <asm/unistd_32.h>
+#  define __ARCH_WANT_IPC_PARSE_VERSION
+#  define __ARCH_WANT_STAT64
+#  define __ARCH_WANT_SYS_OLD_MMAP
+#  define __ARCH_WANT_SYS_OLD_SELECT
+
 # else
-#  include "unistd_64.h"
+
+#  include <asm/unistd_64.h>
+#  define __ARCH_WANT_COMPAT_SYS_TIME
+
 # endif
+
+# define __ARCH_WANT_OLD_READDIR
+# define __ARCH_WANT_OLD_STAT
+# define __ARCH_WANT_SYS_ALARM
+# define __ARCH_WANT_SYS_FADVISE64
+# define __ARCH_WANT_SYS_GETHOSTNAME
+# define __ARCH_WANT_SYS_GETPGRP
+# define __ARCH_WANT_SYS_LLSEEK
+# define __ARCH_WANT_SYS_NICE
+# define __ARCH_WANT_SYS_OLDUMOUNT
+# define __ARCH_WANT_SYS_OLD_GETRLIMIT
+# define __ARCH_WANT_SYS_OLD_UNAME
+# define __ARCH_WANT_SYS_PAUSE
+# define __ARCH_WANT_SYS_RT_SIGACTION
+# define __ARCH_WANT_SYS_RT_SIGSUSPEND
+# define __ARCH_WANT_SYS_SGETMASK
+# define __ARCH_WANT_SYS_SIGNAL
+# define __ARCH_WANT_SYS_SIGPENDING
+# define __ARCH_WANT_SYS_SIGPROCMASK
+# define __ARCH_WANT_SYS_SOCKETCALL
+# define __ARCH_WANT_SYS_TIME
+# define __ARCH_WANT_SYS_UTIME
+# define __ARCH_WANT_SYS_WAITPID
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+# define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+
 #else
 # ifdef __i386__
-#  include "unistd_32.h"
+#  include <asm/unistd_32.h>
 # else
-#  include "unistd_64.h"
+#  include <asm/unistd_64.h>
 # endif
 #endif
+
+#endif /* _ASM_X86_UNISTD_H */
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
deleted file mode 100644 (file)
index 599c77d..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-#ifndef _ASM_X86_UNISTD_32_H
-#define _ASM_X86_UNISTD_32_H
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall      0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-#define __NR_break              17
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_nice               34
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_mpx                56
-#define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_oldolduname        59
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76   /* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_ioperm            101
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-#define __NR_iopl              110
-#define __NR_vhangup           111
-#define __NR_idle              112
-#define __NR_vm86old           113
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_modify_ldt                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_vm86              166
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl              172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_chown             182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_lchown32          198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_chown32           212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-#define __NR_mincore           218
-#define __NR_madvise           219
-#define __NR_madvise1          219     /* delete when C lib stub is removed */
-#define __NR_getdents64                220
-#define __NR_fcntl64           221
-/* 223 is unused */
-#define __NR_gettid            224
-#define __NR_readahead         225
-#define __NR_setxattr          226
-#define __NR_lsetxattr         227
-#define __NR_fsetxattr         228
-#define __NR_getxattr          229
-#define __NR_lgetxattr         230
-#define __NR_fgetxattr         231
-#define __NR_listxattr         232
-#define __NR_llistxattr                233
-#define __NR_flistxattr                234
-#define __NR_removexattr       235
-#define __NR_lremovexattr      236
-#define __NR_fremovexattr      237
-#define __NR_tkill             238
-#define __NR_sendfile64                239
-#define __NR_futex             240
-#define __NR_sched_setaffinity 241
-#define __NR_sched_getaffinity 242
-#define __NR_set_thread_area   243
-#define __NR_get_thread_area   244
-#define __NR_io_setup          245
-#define __NR_io_destroy                246
-#define __NR_io_getevents      247
-#define __NR_io_submit         248
-#define __NR_io_cancel         249
-#define __NR_fadvise64         250
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group                252
-#define __NR_lookup_dcookie    253
-#define __NR_epoll_create      254
-#define __NR_epoll_ctl         255
-#define __NR_epoll_wait                256
-#define __NR_remap_file_pages  257
-#define __NR_set_tid_address   258
-#define __NR_timer_create      259
-#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_statfs64          268
-#define __NR_fstatfs64         269
-#define __NR_tgkill            270
-#define __NR_utimes            271
-#define __NR_fadvise64_64      272
-#define __NR_vserver           273
-#define __NR_mbind             274
-#define __NR_get_mempolicy     275
-#define __NR_set_mempolicy     276
-#define __NR_mq_open           277
-#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_kexec_load                283
-#define __NR_waitid            284
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key           286
-#define __NR_request_key       287
-#define __NR_keyctl            288
-#define __NR_ioprio_set                289
-#define __NR_ioprio_get                290
-#define __NR_inotify_init      291
-#define __NR_inotify_add_watch 292
-#define __NR_inotify_rm_watch  293
-#define __NR_migrate_pages     294
-#define __NR_openat            295
-#define __NR_mkdirat           296
-#define __NR_mknodat           297
-#define __NR_fchownat          298
-#define __NR_futimesat         299
-#define __NR_fstatat64         300
-#define __NR_unlinkat          301
-#define __NR_renameat          302
-#define __NR_linkat            303
-#define __NR_symlinkat         304
-#define __NR_readlinkat                305
-#define __NR_fchmodat          306
-#define __NR_faccessat         307
-#define __NR_pselect6          308
-#define __NR_ppoll             309
-#define __NR_unshare           310
-#define __NR_set_robust_list   311
-#define __NR_get_robust_list   312
-#define __NR_splice            313
-#define __NR_sync_file_range   314
-#define __NR_tee               315
-#define __NR_vmsplice          316
-#define __NR_move_pages                317
-#define __NR_getcpu            318
-#define __NR_epoll_pwait       319
-#define __NR_utimensat         320
-#define __NR_signalfd          321
-#define __NR_timerfd_create    322
-#define __NR_eventfd           323
-#define __NR_fallocate         324
-#define __NR_timerfd_settime   325
-#define __NR_timerfd_gettime   326
-#define __NR_signalfd4         327
-#define __NR_eventfd2          328
-#define __NR_epoll_create1     329
-#define __NR_dup3              330
-#define __NR_pipe2             331
-#define __NR_inotify_init1     332
-#define __NR_preadv            333
-#define __NR_pwritev           334
-#define __NR_rt_tgsigqueueinfo 335
-#define __NR_perf_event_open   336
-#define __NR_recvmmsg          337
-#define __NR_fanotify_init     338
-#define __NR_fanotify_mark     339
-#define __NR_prlimit64         340
-#define __NR_name_to_handle_at 341
-#define __NR_open_by_handle_at  342
-#define __NR_clock_adjtime     343
-#define __NR_syncfs             344
-#define __NR_sendmmsg          345
-#define __NR_setns             346
-#define __NR_process_vm_readv  347
-#define __NR_process_vm_writev 348
-
-#ifdef __KERNEL__
-
-#define NR_syscalls 349
-
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_IPC
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLD_UNAME
-#define __ARCH_WANT_SYS_OLD_MMAP
-#define __ARCH_WANT_SYS_OLD_SELECT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_X86_UNISTD_32_H */
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
deleted file mode 100644 (file)
index 0431f19..0000000
+++ /dev/null
@@ -1,732 +0,0 @@
-#ifndef _ASM_X86_UNISTD_64_H
-#define _ASM_X86_UNISTD_64_H
-
-#ifndef __SYSCALL
-#define __SYSCALL(a, b)
-#endif
-
-/*
- * This file contains the system call numbers.
- *
- * Note: holes are not allowed.
- */
-
-/* at least 8 syscall per cacheline */
-#define __NR_read                              0
-__SYSCALL(__NR_read, sys_read)
-#define __NR_write                             1
-__SYSCALL(__NR_write, sys_write)
-#define __NR_open                              2
-__SYSCALL(__NR_open, sys_open)
-#define __NR_close                             3
-__SYSCALL(__NR_close, sys_close)
-#define __NR_stat                              4
-__SYSCALL(__NR_stat, sys_newstat)
-#define __NR_fstat                             5
-__SYSCALL(__NR_fstat, sys_newfstat)
-#define __NR_lstat                             6
-__SYSCALL(__NR_lstat, sys_newlstat)
-#define __NR_poll                              7
-__SYSCALL(__NR_poll, sys_poll)
-
-#define __NR_lseek                             8
-__SYSCALL(__NR_lseek, sys_lseek)
-#define __NR_mmap                              9
-__SYSCALL(__NR_mmap, sys_mmap)
-#define __NR_mprotect                          10
-__SYSCALL(__NR_mprotect, sys_mprotect)
-#define __NR_munmap                            11
-__SYSCALL(__NR_munmap, sys_munmap)
-#define __NR_brk                               12
-__SYSCALL(__NR_brk, sys_brk)
-#define __NR_rt_sigaction                      13
-__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction)
-#define __NR_rt_sigprocmask                    14
-__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask)
-#define __NR_rt_sigreturn                      15
-__SYSCALL(__NR_rt_sigreturn, stub_rt_sigreturn)
-
-#define __NR_ioctl                             16
-__SYSCALL(__NR_ioctl, sys_ioctl)
-#define __NR_pread64                           17
-__SYSCALL(__NR_pread64, sys_pread64)
-#define __NR_pwrite64                          18
-__SYSCALL(__NR_pwrite64, sys_pwrite64)
-#define __NR_readv                             19
-__SYSCALL(__NR_readv, sys_readv)
-#define __NR_writev                            20
-__SYSCALL(__NR_writev, sys_writev)
-#define __NR_access                            21
-__SYSCALL(__NR_access, sys_access)
-#define __NR_pipe                              22
-__SYSCALL(__NR_pipe, sys_pipe)
-#define __NR_select                            23
-__SYSCALL(__NR_select, sys_select)
-
-#define __NR_sched_yield                       24
-__SYSCALL(__NR_sched_yield, sys_sched_yield)
-#define __NR_mremap                            25
-__SYSCALL(__NR_mremap, sys_mremap)
-#define __NR_msync                             26
-__SYSCALL(__NR_msync, sys_msync)
-#define __NR_mincore                           27
-__SYSCALL(__NR_mincore, sys_mincore)
-#define __NR_madvise                           28
-__SYSCALL(__NR_madvise, sys_madvise)
-#define __NR_shmget                            29
-__SYSCALL(__NR_shmget, sys_shmget)
-#define __NR_shmat                             30
-__SYSCALL(__NR_shmat, sys_shmat)
-#define __NR_shmctl                            31
-__SYSCALL(__NR_shmctl, sys_shmctl)
-
-#define __NR_dup                               32
-__SYSCALL(__NR_dup, sys_dup)
-#define __NR_dup2                              33
-__SYSCALL(__NR_dup2, sys_dup2)
-#define __NR_pause                             34
-__SYSCALL(__NR_pause, sys_pause)
-#define __NR_nanosleep                         35
-__SYSCALL(__NR_nanosleep, sys_nanosleep)
-#define __NR_getitimer                         36
-__SYSCALL(__NR_getitimer, sys_getitimer)
-#define __NR_alarm                             37
-__SYSCALL(__NR_alarm, sys_alarm)
-#define __NR_setitimer                         38
-__SYSCALL(__NR_setitimer, sys_setitimer)
-#define __NR_getpid                            39
-__SYSCALL(__NR_getpid, sys_getpid)
-
-#define __NR_sendfile                          40
-__SYSCALL(__NR_sendfile, sys_sendfile64)
-#define __NR_socket                            41
-__SYSCALL(__NR_socket, sys_socket)
-#define __NR_connect                           42
-__SYSCALL(__NR_connect, sys_connect)
-#define __NR_accept                            43
-__SYSCALL(__NR_accept, sys_accept)
-#define __NR_sendto                            44
-__SYSCALL(__NR_sendto, sys_sendto)
-#define __NR_recvfrom                          45
-__SYSCALL(__NR_recvfrom, sys_recvfrom)
-#define __NR_sendmsg                           46
-__SYSCALL(__NR_sendmsg, sys_sendmsg)
-#define __NR_recvmsg                           47
-__SYSCALL(__NR_recvmsg, sys_recvmsg)
-
-#define __NR_shutdown                          48
-__SYSCALL(__NR_shutdown, sys_shutdown)
-#define __NR_bind                              49
-__SYSCALL(__NR_bind, sys_bind)
-#define __NR_listen                            50
-__SYSCALL(__NR_listen, sys_listen)
-#define __NR_getsockname                       51
-__SYSCALL(__NR_getsockname, sys_getsockname)
-#define __NR_getpeername                       52
-__SYSCALL(__NR_getpeername, sys_getpeername)
-#define __NR_socketpair                                53
-__SYSCALL(__NR_socketpair, sys_socketpair)
-#define __NR_setsockopt                                54
-__SYSCALL(__NR_setsockopt, sys_setsockopt)
-#define __NR_getsockopt                                55
-__SYSCALL(__NR_getsockopt, sys_getsockopt)
-
-#define __NR_clone                             56
-__SYSCALL(__NR_clone, stub_clone)
-#define __NR_fork                              57
-__SYSCALL(__NR_fork, stub_fork)
-#define __NR_vfork                             58
-__SYSCALL(__NR_vfork, stub_vfork)
-#define __NR_execve                            59
-__SYSCALL(__NR_execve, stub_execve)
-#define __NR_exit                              60
-__SYSCALL(__NR_exit, sys_exit)
-#define __NR_wait4                             61
-__SYSCALL(__NR_wait4, sys_wait4)
-#define __NR_kill                              62
-__SYSCALL(__NR_kill, sys_kill)
-#define __NR_uname                             63
-__SYSCALL(__NR_uname, sys_newuname)
-
-#define __NR_semget                            64
-__SYSCALL(__NR_semget, sys_semget)
-#define __NR_semop                             65
-__SYSCALL(__NR_semop, sys_semop)
-#define __NR_semctl                            66
-__SYSCALL(__NR_semctl, sys_semctl)
-#define __NR_shmdt                             67
-__SYSCALL(__NR_shmdt, sys_shmdt)
-#define __NR_msgget                            68
-__SYSCALL(__NR_msgget, sys_msgget)
-#define __NR_msgsnd                            69
-__SYSCALL(__NR_msgsnd, sys_msgsnd)
-#define __NR_msgrcv                            70
-__SYSCALL(__NR_msgrcv, sys_msgrcv)
-#define __NR_msgctl                            71
-__SYSCALL(__NR_msgctl, sys_msgctl)
-
-#define __NR_fcntl                             72
-__SYSCALL(__NR_fcntl, sys_fcntl)
-#define __NR_flock                             73
-__SYSCALL(__NR_flock, sys_flock)
-#define __NR_fsync                             74
-__SYSCALL(__NR_fsync, sys_fsync)
-#define __NR_fdatasync                         75
-__SYSCALL(__NR_fdatasync, sys_fdatasync)
-#define __NR_truncate                          76
-__SYSCALL(__NR_truncate, sys_truncate)
-#define __NR_ftruncate                         77
-__SYSCALL(__NR_ftruncate, sys_ftruncate)
-#define __NR_getdents                          78
-__SYSCALL(__NR_getdents, sys_getdents)
-#define __NR_getcwd                            79
-__SYSCALL(__NR_getcwd, sys_getcwd)
-
-#define __NR_chdir                             80
-__SYSCALL(__NR_chdir, sys_chdir)
-#define __NR_fchdir                            81
-__SYSCALL(__NR_fchdir, sys_fchdir)
-#define __NR_rename                            82
-__SYSCALL(__NR_rename, sys_rename)
-#define __NR_mkdir                             83
-__SYSCALL(__NR_mkdir, sys_mkdir)
-#define __NR_rmdir                             84
-__SYSCALL(__NR_rmdir, sys_rmdir)
-#define __NR_creat                             85
-__SYSCALL(__NR_creat, sys_creat)
-#define __NR_link                              86
-__SYSCALL(__NR_link, sys_link)
-#define __NR_unlink                            87
-__SYSCALL(__NR_unlink, sys_unlink)
-
-#define __NR_symlink                           88
-__SYSCALL(__NR_symlink, sys_symlink)
-#define __NR_readlink                          89
-__SYSCALL(__NR_readlink, sys_readlink)
-#define __NR_chmod                             90
-__SYSCALL(__NR_chmod, sys_chmod)
-#define __NR_fchmod                            91
-__SYSCALL(__NR_fchmod, sys_fchmod)
-#define __NR_chown                             92
-__SYSCALL(__NR_chown, sys_chown)
-#define __NR_fchown                            93
-__SYSCALL(__NR_fchown, sys_fchown)
-#define __NR_lchown                            94
-__SYSCALL(__NR_lchown, sys_lchown)
-#define __NR_umask                             95
-__SYSCALL(__NR_umask, sys_umask)
-
-#define __NR_gettimeofday                      96
-__SYSCALL(__NR_gettimeofday, sys_gettimeofday)
-#define __NR_getrlimit                         97
-__SYSCALL(__NR_getrlimit, sys_getrlimit)
-#define __NR_getrusage                         98
-__SYSCALL(__NR_getrusage, sys_getrusage)
-#define __NR_sysinfo                           99
-__SYSCALL(__NR_sysinfo, sys_sysinfo)
-#define __NR_times                             100
-__SYSCALL(__NR_times, sys_times)
-#define __NR_ptrace                            101
-__SYSCALL(__NR_ptrace, sys_ptrace)
-#define __NR_getuid                            102
-__SYSCALL(__NR_getuid, sys_getuid)
-#define __NR_syslog                            103
-__SYSCALL(__NR_syslog, sys_syslog)
-
-/* at the very end the stuff that never runs during the benchmarks */
-#define __NR_getgid                            104
-__SYSCALL(__NR_getgid, sys_getgid)
-#define __NR_setuid                            105
-__SYSCALL(__NR_setuid, sys_setuid)
-#define __NR_setgid                            106
-__SYSCALL(__NR_setgid, sys_setgid)
-#define __NR_geteuid                           107
-__SYSCALL(__NR_geteuid, sys_geteuid)
-#define __NR_getegid                           108
-__SYSCALL(__NR_getegid, sys_getegid)
-#define __NR_setpgid                           109
-__SYSCALL(__NR_setpgid, sys_setpgid)
-#define __NR_getppid                           110
-__SYSCALL(__NR_getppid, sys_getppid)
-#define __NR_getpgrp                           111
-__SYSCALL(__NR_getpgrp, sys_getpgrp)
-
-#define __NR_setsid                            112
-__SYSCALL(__NR_setsid, sys_setsid)
-#define __NR_setreuid                          113
-__SYSCALL(__NR_setreuid, sys_setreuid)
-#define __NR_setregid                          114
-__SYSCALL(__NR_setregid, sys_setregid)
-#define __NR_getgroups                         115
-__SYSCALL(__NR_getgroups, sys_getgroups)
-#define __NR_setgroups                         116
-__SYSCALL(__NR_setgroups, sys_setgroups)
-#define __NR_setresuid                         117
-__SYSCALL(__NR_setresuid, sys_setresuid)
-#define __NR_getresuid                         118
-__SYSCALL(__NR_getresuid, sys_getresuid)
-#define __NR_setresgid                         119
-__SYSCALL(__NR_setresgid, sys_setresgid)
-
-#define __NR_getresgid                         120
-__SYSCALL(__NR_getresgid, sys_getresgid)
-#define __NR_getpgid                           121
-__SYSCALL(__NR_getpgid, sys_getpgid)
-#define __NR_setfsuid                          122
-__SYSCALL(__NR_setfsuid, sys_setfsuid)
-#define __NR_setfsgid                          123
-__SYSCALL(__NR_setfsgid, sys_setfsgid)
-#define __NR_getsid                            124
-__SYSCALL(__NR_getsid, sys_getsid)
-#define __NR_capget                            125
-__SYSCALL(__NR_capget, sys_capget)
-#define __NR_capset                            126
-__SYSCALL(__NR_capset, sys_capset)
-
-#define __NR_rt_sigpending                     127
-__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending)
-#define __NR_rt_sigtimedwait                   128
-__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)
-#define __NR_rt_sigqueueinfo                   129
-__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo)
-#define __NR_rt_sigsuspend                     130
-__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend)
-#define __NR_sigaltstack                       131
-__SYSCALL(__NR_sigaltstack, stub_sigaltstack)
-#define __NR_utime                             132
-__SYSCALL(__NR_utime, sys_utime)
-#define __NR_mknod                             133
-__SYSCALL(__NR_mknod, sys_mknod)
-
-/* Only needed for a.out */
-#define __NR_uselib                            134
-__SYSCALL(__NR_uselib, sys_ni_syscall)
-#define __NR_personality                       135
-__SYSCALL(__NR_personality, sys_personality)
-
-#define __NR_ustat                             136
-__SYSCALL(__NR_ustat, sys_ustat)
-#define __NR_statfs                            137
-__SYSCALL(__NR_statfs, sys_statfs)
-#define __NR_fstatfs                           138
-__SYSCALL(__NR_fstatfs, sys_fstatfs)
-#define __NR_sysfs                             139
-__SYSCALL(__NR_sysfs, sys_sysfs)
-
-#define __NR_getpriority                       140
-__SYSCALL(__NR_getpriority, sys_getpriority)
-#define __NR_setpriority                       141
-__SYSCALL(__NR_setpriority, sys_setpriority)
-#define __NR_sched_setparam                    142
-__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
-#define __NR_sched_getparam                    143
-__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
-#define __NR_sched_setscheduler                        144
-__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
-#define __NR_sched_getscheduler                        145
-__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
-#define __NR_sched_get_priority_max            146
-__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
-#define __NR_sched_get_priority_min            147
-__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
-#define __NR_sched_rr_get_interval             148
-__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval)
-
-#define __NR_mlock                             149
-__SYSCALL(__NR_mlock, sys_mlock)
-#define __NR_munlock                           150
-__SYSCALL(__NR_munlock, sys_munlock)
-#define __NR_mlockall                          151
-__SYSCALL(__NR_mlockall, sys_mlockall)
-#define __NR_munlockall                                152
-__SYSCALL(__NR_munlockall, sys_munlockall)
-
-#define __NR_vhangup                           153
-__SYSCALL(__NR_vhangup, sys_vhangup)
-
-#define __NR_modify_ldt                                154
-__SYSCALL(__NR_modify_ldt, sys_modify_ldt)
-
-#define __NR_pivot_root                                155
-__SYSCALL(__NR_pivot_root, sys_pivot_root)
-
-#define __NR__sysctl                           156
-__SYSCALL(__NR__sysctl, sys_sysctl)
-
-#define __NR_prctl                             157
-__SYSCALL(__NR_prctl, sys_prctl)
-#define __NR_arch_prctl                                158
-__SYSCALL(__NR_arch_prctl, sys_arch_prctl)
-
-#define __NR_adjtimex                          159
-__SYSCALL(__NR_adjtimex, sys_adjtimex)
-
-#define __NR_setrlimit                         160
-__SYSCALL(__NR_setrlimit, sys_setrlimit)
-
-#define __NR_chroot                            161
-__SYSCALL(__NR_chroot, sys_chroot)
-
-#define __NR_sync                              162
-__SYSCALL(__NR_sync, sys_sync)
-
-#define __NR_acct                              163
-__SYSCALL(__NR_acct, sys_acct)
-
-#define __NR_settimeofday                      164
-__SYSCALL(__NR_settimeofday, sys_settimeofday)
-
-#define __NR_mount                             165
-__SYSCALL(__NR_mount, sys_mount)
-#define __NR_umount2                           166
-__SYSCALL(__NR_umount2, sys_umount)
-
-#define __NR_swapon                            167
-__SYSCALL(__NR_swapon, sys_swapon)
-#define __NR_swapoff                           168
-__SYSCALL(__NR_swapoff, sys_swapoff)
-
-#define __NR_reboot                            169
-__SYSCALL(__NR_reboot, sys_reboot)
-
-#define __NR_sethostname                       170
-__SYSCALL(__NR_sethostname, sys_sethostname)
-#define __NR_setdomainname                     171
-__SYSCALL(__NR_setdomainname, sys_setdomainname)
-
-#define __NR_iopl                              172
-__SYSCALL(__NR_iopl, stub_iopl)
-#define __NR_ioperm                            173
-__SYSCALL(__NR_ioperm, sys_ioperm)
-
-#define __NR_create_module                     174
-__SYSCALL(__NR_create_module, sys_ni_syscall)
-#define __NR_init_module                       175
-__SYSCALL(__NR_init_module, sys_init_module)
-#define __NR_delete_module                     176
-__SYSCALL(__NR_delete_module, sys_delete_module)
-#define __NR_get_kernel_syms                   177
-__SYSCALL(__NR_get_kernel_syms, sys_ni_syscall)
-#define __NR_query_module                      178
-__SYSCALL(__NR_query_module, sys_ni_syscall)
-
-#define __NR_quotactl                          179
-__SYSCALL(__NR_quotactl, sys_quotactl)
-
-#define __NR_nfsservctl                                180
-__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
-
-/* reserved for LiS/STREAMS */
-#define __NR_getpmsg                           181
-__SYSCALL(__NR_getpmsg, sys_ni_syscall)
-#define __NR_putpmsg                           182
-__SYSCALL(__NR_putpmsg, sys_ni_syscall)
-
-/* reserved for AFS */
-#define __NR_afs_syscall                       183
-__SYSCALL(__NR_afs_syscall, sys_ni_syscall)
-
-/* reserved for tux */
-#define __NR_tuxcall                           184
-__SYSCALL(__NR_tuxcall, sys_ni_syscall)
-
-#define __NR_security                          185
-__SYSCALL(__NR_security, sys_ni_syscall)
-
-#define __NR_gettid                            186
-__SYSCALL(__NR_gettid, sys_gettid)
-
-#define __NR_readahead                         187
-__SYSCALL(__NR_readahead, sys_readahead)
-#define __NR_setxattr                          188
-__SYSCALL(__NR_setxattr, sys_setxattr)
-#define __NR_lsetxattr                         189
-__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
-#define __NR_fsetxattr                         190
-__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
-#define __NR_getxattr                          191
-__SYSCALL(__NR_getxattr, sys_getxattr)
-#define __NR_lgetxattr                         192
-__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
-#define __NR_fgetxattr                         193
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
-#define __NR_listxattr                         194
-__SYSCALL(__NR_listxattr, sys_listxattr)
-#define __NR_llistxattr                                195
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
-#define __NR_flistxattr                                196
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
-#define __NR_removexattr                       197
-__SYSCALL(__NR_removexattr, sys_removexattr)
-#define __NR_lremovexattr                      198
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
-#define __NR_fremovexattr                      199
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
-#define __NR_tkill                             200
-__SYSCALL(__NR_tkill, sys_tkill)
-#define __NR_time                              201
-__SYSCALL(__NR_time, sys_time)
-#define __NR_futex                             202
-__SYSCALL(__NR_futex, sys_futex)
-#define __NR_sched_setaffinity                 203
-__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity)
-#define __NR_sched_getaffinity                 204
-__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
-#define __NR_set_thread_area                   205
-__SYSCALL(__NR_set_thread_area, sys_ni_syscall)        /* use arch_prctl */
-#define __NR_io_setup                          206
-__SYSCALL(__NR_io_setup, sys_io_setup)
-#define __NR_io_destroy                                207
-__SYSCALL(__NR_io_destroy, sys_io_destroy)
-#define __NR_io_getevents                      208
-__SYSCALL(__NR_io_getevents, sys_io_getevents)
-#define __NR_io_submit                         209
-__SYSCALL(__NR_io_submit, sys_io_submit)
-#define __NR_io_cancel                         210
-__SYSCALL(__NR_io_cancel, sys_io_cancel)
-#define __NR_get_thread_area                   211
-__SYSCALL(__NR_get_thread_area, sys_ni_syscall)        /* use arch_prctl */
-#define __NR_lookup_dcookie                    212
-__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
-#define __NR_epoll_create                      213
-__SYSCALL(__NR_epoll_create, sys_epoll_create)
-#define __NR_epoll_ctl_old                     214
-__SYSCALL(__NR_epoll_ctl_old, sys_ni_syscall)
-#define __NR_epoll_wait_old                    215
-__SYSCALL(__NR_epoll_wait_old, sys_ni_syscall)
-#define __NR_remap_file_pages                  216
-__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
-#define __NR_getdents64                                217
-__SYSCALL(__NR_getdents64, sys_getdents64)
-#define __NR_set_tid_address                   218
-__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
-#define __NR_restart_syscall                   219
-__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
-#define __NR_semtimedop                                220
-__SYSCALL(__NR_semtimedop, sys_semtimedop)
-#define __NR_fadvise64                         221
-__SYSCALL(__NR_fadvise64, sys_fadvise64)
-#define __NR_timer_create                      222
-__SYSCALL(__NR_timer_create, sys_timer_create)
-#define __NR_timer_settime                     223
-__SYSCALL(__NR_timer_settime, sys_timer_settime)
-#define __NR_timer_gettime                     224
-__SYSCALL(__NR_timer_gettime, sys_timer_gettime)
-#define __NR_timer_getoverrun                  225
-__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
-#define __NR_timer_delete                      226
-__SYSCALL(__NR_timer_delete, sys_timer_delete)
-#define __NR_clock_settime                     227
-__SYSCALL(__NR_clock_settime, sys_clock_settime)
-#define __NR_clock_gettime                     228
-__SYSCALL(__NR_clock_gettime, sys_clock_gettime)
-#define __NR_clock_getres                      229
-__SYSCALL(__NR_clock_getres, sys_clock_getres)
-#define __NR_clock_nanosleep                   230
-__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep)
-#define __NR_exit_group                                231
-__SYSCALL(__NR_exit_group, sys_exit_group)
-#define __NR_epoll_wait                                232
-__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
-#define __NR_epoll_ctl                         233
-__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
-#define __NR_tgkill                            234
-__SYSCALL(__NR_tgkill, sys_tgkill)
-#define __NR_utimes                            235
-__SYSCALL(__NR_utimes, sys_utimes)
-#define __NR_vserver                           236
-__SYSCALL(__NR_vserver, sys_ni_syscall)
-#define __NR_mbind                             237
-__SYSCALL(__NR_mbind, sys_mbind)
-#define __NR_set_mempolicy                     238
-__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
-#define __NR_get_mempolicy                     239
-__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
-#define __NR_mq_open                           240
-__SYSCALL(__NR_mq_open, sys_mq_open)
-#define __NR_mq_unlink                         241
-__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
-#define __NR_mq_timedsend                      242
-__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend)
-#define __NR_mq_timedreceive                   243
-__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive)
-#define __NR_mq_notify                         244
-__SYSCALL(__NR_mq_notify, sys_mq_notify)
-#define __NR_mq_getsetattr                     245
-__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
-#define __NR_kexec_load                                246
-__SYSCALL(__NR_kexec_load, sys_kexec_load)
-#define __NR_waitid                            247
-__SYSCALL(__NR_waitid, sys_waitid)
-#define __NR_add_key                           248
-__SYSCALL(__NR_add_key, sys_add_key)
-#define __NR_request_key                       249
-__SYSCALL(__NR_request_key, sys_request_key)
-#define __NR_keyctl                            250
-__SYSCALL(__NR_keyctl, sys_keyctl)
-#define __NR_ioprio_set                                251
-__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
-#define __NR_ioprio_get                                252
-__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
-#define __NR_inotify_init                      253
-__SYSCALL(__NR_inotify_init, sys_inotify_init)
-#define __NR_inotify_add_watch                 254
-__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
-#define __NR_inotify_rm_watch                  255
-__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
-#define __NR_migrate_pages                     256
-__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
-#define __NR_openat                            257
-__SYSCALL(__NR_openat, sys_openat)
-#define __NR_mkdirat                           258
-__SYSCALL(__NR_mkdirat, sys_mkdirat)
-#define __NR_mknodat                           259
-__SYSCALL(__NR_mknodat, sys_mknodat)
-#define __NR_fchownat                          260
-__SYSCALL(__NR_fchownat, sys_fchownat)
-#define __NR_futimesat                         261
-__SYSCALL(__NR_futimesat, sys_futimesat)
-#define __NR_newfstatat                                262
-__SYSCALL(__NR_newfstatat, sys_newfstatat)
-#define __NR_unlinkat                          263
-__SYSCALL(__NR_unlinkat, sys_unlinkat)
-#define __NR_renameat                          264
-__SYSCALL(__NR_renameat, sys_renameat)
-#define __NR_linkat                            265
-__SYSCALL(__NR_linkat, sys_linkat)
-#define __NR_symlinkat                         266
-__SYSCALL(__NR_symlinkat, sys_symlinkat)
-#define __NR_readlinkat                                267
-__SYSCALL(__NR_readlinkat, sys_readlinkat)
-#define __NR_fchmodat                          268
-__SYSCALL(__NR_fchmodat, sys_fchmodat)
-#define __NR_faccessat                         269
-__SYSCALL(__NR_faccessat, sys_faccessat)
-#define __NR_pselect6                          270
-__SYSCALL(__NR_pselect6, sys_pselect6)
-#define __NR_ppoll                             271
-__SYSCALL(__NR_ppoll,  sys_ppoll)
-#define __NR_unshare                           272
-__SYSCALL(__NR_unshare,        sys_unshare)
-#define __NR_set_robust_list                   273
-__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
-#define __NR_get_robust_list                   274
-__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
-#define __NR_splice                            275
-__SYSCALL(__NR_splice, sys_splice)
-#define __NR_tee                               276
-__SYSCALL(__NR_tee, sys_tee)
-#define __NR_sync_file_range                   277
-__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
-#define __NR_vmsplice                          278
-__SYSCALL(__NR_vmsplice, sys_vmsplice)
-#define __NR_move_pages                                279
-__SYSCALL(__NR_move_pages, sys_move_pages)
-#define __NR_utimensat                         280
-__SYSCALL(__NR_utimensat, sys_utimensat)
-#define __NR_epoll_pwait                       281
-__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
-#define __NR_signalfd                          282
-__SYSCALL(__NR_signalfd, sys_signalfd)
-#define __NR_timerfd_create                    283
-__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
-#define __NR_eventfd                           284
-__SYSCALL(__NR_eventfd, sys_eventfd)
-#define __NR_fallocate                         285
-__SYSCALL(__NR_fallocate, sys_fallocate)
-#define __NR_timerfd_settime                   286
-__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
-#define __NR_timerfd_gettime                   287
-__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
-#define __NR_accept4                           288
-__SYSCALL(__NR_accept4, sys_accept4)
-#define __NR_signalfd4                         289
-__SYSCALL(__NR_signalfd4, sys_signalfd4)
-#define __NR_eventfd2                          290
-__SYSCALL(__NR_eventfd2, sys_eventfd2)
-#define __NR_epoll_create1                     291
-__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
-#define __NR_dup3                              292
-__SYSCALL(__NR_dup3, sys_dup3)
-#define __NR_pipe2                             293
-__SYSCALL(__NR_pipe2, sys_pipe2)
-#define __NR_inotify_init1                     294
-__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
-#define __NR_preadv                            295
-__SYSCALL(__NR_preadv, sys_preadv)
-#define __NR_pwritev                           296
-__SYSCALL(__NR_pwritev, sys_pwritev)
-#define __NR_rt_tgsigqueueinfo                 297
-__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
-#define __NR_perf_event_open                   298
-__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
-#define __NR_recvmmsg                          299
-__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
-#define __NR_fanotify_init                     300
-__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
-#define __NR_fanotify_mark                     301
-__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
-#define __NR_prlimit64                         302
-__SYSCALL(__NR_prlimit64, sys_prlimit64)
-#define __NR_name_to_handle_at                 303
-__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
-#define __NR_open_by_handle_at                 304
-__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
-#define __NR_clock_adjtime                     305
-__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
-#define __NR_syncfs                             306
-__SYSCALL(__NR_syncfs, sys_syncfs)
-#define __NR_sendmmsg                          307
-__SYSCALL(__NR_sendmmsg, sys_sendmmsg)
-#define __NR_setns                             308
-__SYSCALL(__NR_setns, sys_setns)
-#define __NR_getcpu                            309
-__SYSCALL(__NR_getcpu, sys_getcpu)
-#define __NR_process_vm_readv                  310
-__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv)
-#define __NR_process_vm_writev                 311
-__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)
-
-#ifndef __NO_STUBS
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLD_UNAME
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_COMPAT_SYS_TIME
-#endif /* __NO_STUBS */
-
-#ifdef __KERNEL__
-
-#ifndef COMPILE_OFFSETS
-#include <asm/asm-offsets.h>
-#define NR_syscalls (__NR_syscall_max + 1)
-#endif
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_X86_UNISTD_64_H */
index 02b2f05b371e9a8a8c84fb2f0bd5742b1d8d6963..5369059c07a907fac7e6a755aa24e7ae280bd6a0 100644 (file)
@@ -25,7 +25,8 @@ obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y                  += probe_roms.o
 obj-$(CONFIG_X86_32)   += sys_i386_32.o i386_ksyms_32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o x8664_ksyms_64.o
-obj-$(CONFIG_X86_64)   += syscall_64.o vsyscall_64.o
+obj-y                  += syscall_$(BITS).o
+obj-$(CONFIG_X86_64)   += vsyscall_64.o
 obj-$(CONFIG_X86_64)   += vsyscall_emu_64.o
 obj-y                  += bootflag.o e820.o
 obj-y                  += pci-dma.o quirks.o topology.o kdebugfs.o
index 395a10e68067625e783b0ed1f8546231727ac230..85d98ab15cdcfd019c1d8bc6ece2f049ace07b65 100644 (file)
@@ -3,6 +3,11 @@
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
 
+#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+static char syscalls[] = {
+#include <asm/syscalls_32.h>
+};
+
 /* workaround for a warning with -Wmissing-prototypes */
 void foo(void);
 
@@ -76,4 +81,7 @@ void foo(void)
        OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode);
        OFFSET(LGUEST_PAGES_regs, lguest_pages, regs);
 #endif
+       BLANK();
+       DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+       DEFINE(NR_syscalls, sizeof(syscalls));
 }
index e72a1194af22a76707a9f44865b8211b4b1e1e7c..834e897b1e25b66e864d010266e5df29fecfb892 100644 (file)
@@ -1,11 +1,12 @@
 #include <asm/ia32.h>
 
-#define __NO_STUBS 1
-#undef __SYSCALL
-#undef _ASM_X86_UNISTD_64_H
-#define __SYSCALL(nr, sym) [nr] = 1,
-static char syscalls[] = {
-#include <asm/unistd.h>
+#define __SYSCALL_64(nr, sym, compat) [nr] = 1,
+static char syscalls_64[] = {
+#include <asm/syscalls_64.h>
+};
+#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+static char syscalls_ia32[] = {
+#include <asm/syscalls_32.h>
 };
 
 int main(void)
@@ -72,7 +73,11 @@ int main(void)
        OFFSET(TSS_ist, tss_struct, x86_tss.ist);
        BLANK();
 
-       DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+       DEFINE(__NR_syscall_max, sizeof(syscalls_64) - 1);
+       DEFINE(NR_syscalls, sizeof(syscalls_64));
+
+       DEFINE(__NR_ia32_syscall_max, sizeof(syscalls_ia32) - 1);
+       DEFINE(IA32_NR_syscalls, sizeof(syscalls_ia32));
 
        return 0;
 }
index 29ba3297e48006bea5987678bb4806d3c534fc2c..5a11ae2e9e917a07eae73246c7a73ace07edda39 100644 (file)
@@ -1859,7 +1859,7 @@ static struct bus_type mce_subsys = {
        .dev_name       = "machinecheck",
 };
 
-DEFINE_PER_CPU(struct device, mce_device);
+struct device *mce_device[CONFIG_NR_CPUS];
 
 __cpuinitdata
 void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
@@ -2001,19 +2001,27 @@ static struct device_attribute *mce_device_attrs[] = {
 
 static cpumask_var_t mce_device_initialized;
 
+static void mce_device_release(struct device *dev)
+{
+       kfree(dev);
+}
+
 /* Per cpu device init. All of the cpus still share the same ctrl bank: */
 static __cpuinit int mce_device_create(unsigned int cpu)
 {
-       struct device *dev = &per_cpu(mce_device, cpu);
+       struct device *dev;
        int err;
        int i, j;
 
        if (!mce_available(&boot_cpu_data))
                return -EIO;
 
-       memset(dev, 0, sizeof(struct device));
+       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
        dev->id  = cpu;
        dev->bus = &mce_subsys;
+       dev->release = &mce_device_release;
 
        err = device_register(dev);
        if (err)
@@ -2030,6 +2038,7 @@ static __cpuinit int mce_device_create(unsigned int cpu)
                        goto error2;
        }
        cpumask_set_cpu(cpu, mce_device_initialized);
+       mce_device[cpu] = dev;
 
        return 0;
 error2:
@@ -2046,7 +2055,7 @@ error:
 
 static __cpuinit void mce_device_remove(unsigned int cpu)
 {
-       struct device *dev = &per_cpu(mce_device, cpu);
+       struct device *dev = mce_device[cpu];
        int i;
 
        if (!cpumask_test_cpu(cpu, mce_device_initialized))
@@ -2060,6 +2069,7 @@ static __cpuinit void mce_device_remove(unsigned int cpu)
 
        device_unregister(dev);
        cpumask_clear_cpu(cpu, mce_device_initialized);
+       mce_device[cpu] = NULL;
 }
 
 /* Make sure there are no machine checks on offlined CPUs. */
index ba0b94a7e2040fcbd09de26a8729628758fd3370..786e76a86322c99ffd67a6fd9ebf03f85b1d36a3 100644 (file)
@@ -523,6 +523,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 {
        int i, err = 0;
        struct threshold_bank *b = NULL;
+       struct device *dev = mce_device[cpu];
        char name[32];
 
        sprintf(name, "threshold_bank%i", bank);
@@ -543,8 +544,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                if (!b)
                        goto out;
 
-               err = sysfs_create_link(&per_cpu(mce_device, cpu).kobj,
-                                       b->kobj, name);
+               err = sysfs_create_link(&dev->kobj, b->kobj, name);
                if (err)
                        goto out;
 
@@ -565,7 +565,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                goto out;
        }
 
-       b->kobj = kobject_create_and_add(name, &per_cpu(mce_device, cpu).kobj);
+       b->kobj = kobject_create_and_add(name, &dev->kobj);
        if (!b->kobj)
                goto out_free;
 
@@ -585,8 +585,9 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                if (i == cpu)
                        continue;
 
-               err = sysfs_create_link(&per_cpu(mce_device, i).kobj,
-                                       b->kobj, name);
+               dev = mce_device[i];
+               if (dev)
+                       err = sysfs_create_link(&dev->kobj,b->kobj, name);
                if (err)
                        goto out;
 
@@ -649,6 +650,7 @@ static void deallocate_threshold_block(unsigned int cpu,
 static void threshold_remove_bank(unsigned int cpu, int bank)
 {
        struct threshold_bank *b;
+       struct device *dev;
        char name[32];
        int i = 0;
 
@@ -663,7 +665,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 #ifdef CONFIG_SMP
        /* sibling symlink */
        if (shared_bank[bank] && b->blocks->cpu != cpu) {
-               sysfs_remove_link(&per_cpu(mce_device, cpu).kobj, name);
+               sysfs_remove_link(&mce_device[cpu]->kobj, name);
                per_cpu(threshold_banks, cpu)[bank] = NULL;
 
                return;
@@ -675,7 +677,9 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
                if (i == cpu)
                        continue;
 
-               sysfs_remove_link(&per_cpu(mce_device, i).kobj, name);
+               dev = mce_device[i];
+               if (dev)
+                       sysfs_remove_link(&dev->kobj, name);
                per_cpu(threshold_banks, i)[bank] = NULL;
        }
 
index 22d0e21b4dd793fa509e52541bf9b57e7778d1d7..4af9fd2450a5e7f319f6077c75cb8a3bfca89fae 100644 (file)
@@ -81,8 +81,6 @@
  * enough to patch inline, increasing performance.
  */
 
-#define nr_syscalls ((syscall_table_size)/4)
-
 #ifdef CONFIG_PREEMPT
 #define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
 #else
@@ -423,7 +421,7 @@ sysenter_past_esp:
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
        jnz sysenter_audit
 sysenter_do_call:
-       cmpl $(nr_syscalls), %eax
+       cmpl $(NR_syscalls), %eax
        jae syscall_badsys
        call *sys_call_table(,%eax,4)
        movl %eax,PT_EAX(%esp)
@@ -504,7 +502,7 @@ ENTRY(system_call)
                                        # system call tracing in operation / emulation
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
        jnz syscall_trace_entry
-       cmpl $(nr_syscalls), %eax
+       cmpl $(NR_syscalls), %eax
        jae syscall_badsys
 syscall_call:
        call *sys_call_table(,%eax,4)
@@ -654,7 +652,7 @@ syscall_trace_entry:
        movl %esp, %eax
        call syscall_trace_enter
        /* What it returned is what we'll actually use.  */
-       cmpl $(nr_syscalls), %eax
+       cmpl $(NR_syscalls), %eax
        jnae syscall_call
        jmp syscall_exit
 END(syscall_trace_entry)
@@ -694,29 +692,28 @@ END(syscall_badsys)
  * System calls that need a pt_regs pointer.
  */
 #define PTREGSCALL0(name) \
-       ALIGN; \
-ptregs_##name: \
+ENTRY(ptregs_##name) ;  \
        leal 4(%esp),%eax; \
-       jmp sys_##name;
+       jmp sys_##name; \
+ENDPROC(ptregs_##name)
 
 #define PTREGSCALL1(name) \
-       ALIGN; \
-ptregs_##name: \
+ENTRY(ptregs_##name) ; \
        leal 4(%esp),%edx; \
        movl (PT_EBX+4)(%esp),%eax; \
-       jmp sys_##name;
+       jmp sys_##name; \
+ENDPROC(ptregs_##name)
 
 #define PTREGSCALL2(name) \
-       ALIGN; \
-ptregs_##name: \
+ENTRY(ptregs_##name) ; \
        leal 4(%esp),%ecx; \
        movl (PT_ECX+4)(%esp),%edx; \
        movl (PT_EBX+4)(%esp),%eax; \
-       jmp sys_##name;
+       jmp sys_##name; \
+ENDPROC(ptregs_##name)
 
 #define PTREGSCALL3(name) \
-       ALIGN; \
-ptregs_##name: \
+ENTRY(ptregs_##name) ; \
        CFI_STARTPROC; \
        leal 4(%esp),%eax; \
        pushl_cfi %eax; \
@@ -741,8 +738,7 @@ PTREGSCALL2(vm86)
 PTREGSCALL1(vm86old)
 
 /* Clone is an oddball.  The 4th arg is in %edi */
-       ALIGN;
-ptregs_clone:
+ENTRY(ptregs_clone)
        CFI_STARTPROC
        leal 4(%esp),%eax
        pushl_cfi %eax
@@ -1213,11 +1209,6 @@ return_to_handler:
        jmp *%ecx
 #endif
 
-.section .rodata,"a"
-#include "syscall_table_32.S"
-
-syscall_table_size=(.-sys_call_table)
-
 /*
  * Some functions should be protected against kprobes
  */
diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c
new file mode 100644 (file)
index 0000000..147fcd4
--- /dev/null
@@ -0,0 +1,25 @@
+/* System call table for i386. */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+#include <asm/asm-offsets.h>
+
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
+#include <asm/syscalls_32.h>
+#undef __SYSCALL_I386
+
+#define __SYSCALL_I386(nr, sym, compat) [nr] = sym,
+
+typedef asmlinkage void (*sys_call_ptr_t)(void);
+
+extern asmlinkage void sys_ni_syscall(void);
+
+const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+       /*
+        * Smells like a compiler bug -- it doesn't work
+        * when the & below is removed.
+        */
+       [0 ... __NR_syscall_max] = &sys_ni_syscall,
+#include <asm/syscalls_32.h>
+};
index de87d6008295c5459aa1cbc9f41037829e1c82c8..7ac7943be02cb0bb69577daa0403b08372d82da4 100644 (file)
@@ -5,15 +5,11 @@
 #include <linux/cache.h>
 #include <asm/asm-offsets.h>
 
-#define __NO_STUBS
+#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
+#include <asm/syscalls_64.h>
+#undef __SYSCALL_64
 
-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_UNISTD_64_H
-#include <asm/unistd_64.h>
-
-#undef __SYSCALL
-#define __SYSCALL(nr, sym) [nr] = sym,
-#undef _ASM_X86_UNISTD_64_H
+#define __SYSCALL_64(nr, sym, compat) [nr] = sym,
 
 typedef void (*sys_call_ptr_t)(void);
 
@@ -21,9 +17,9 @@ extern void sys_ni_syscall(void);
 
 const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
        /*
-       *Smells like a like a compiler bug -- it doesn't work
-       *when the & below is removed.
-       */
+        * Smells like a compiler bug -- it doesn't work
+        * when the & below is removed.
+        */
        [0 ... __NR_syscall_max] = &sys_ni_syscall,
-#include <asm/unistd_64.h>
+#include <asm/syscalls_64.h>
 };
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
deleted file mode 100644 (file)
index 9a0e312..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-ENTRY(sys_call_table)
-       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
-       .long sys_exit
-       .long ptregs_fork
-       .long sys_read
-       .long sys_write
-       .long sys_open          /* 5 */
-       .long sys_close
-       .long sys_waitpid
-       .long sys_creat
-       .long sys_link
-       .long sys_unlink        /* 10 */
-       .long ptregs_execve
-       .long sys_chdir
-       .long sys_time
-       .long sys_mknod
-       .long sys_chmod         /* 15 */
-       .long sys_lchown16
-       .long sys_ni_syscall    /* old break syscall holder */
-       .long sys_stat
-       .long sys_lseek
-       .long sys_getpid        /* 20 */
-       .long sys_mount
-       .long sys_oldumount
-       .long sys_setuid16
-       .long sys_getuid16
-       .long sys_stime         /* 25 */
-       .long sys_ptrace
-       .long sys_alarm
-       .long sys_fstat
-       .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall    /* old stty syscall holder */
-       .long sys_ni_syscall    /* old gtty syscall holder */
-       .long sys_access
-       .long sys_nice
-       .long sys_ni_syscall    /* 35 - old ftime syscall holder */
-       .long sys_sync
-       .long sys_kill
-       .long sys_rename
-       .long sys_mkdir
-       .long sys_rmdir         /* 40 */
-       .long sys_dup
-       .long sys_pipe
-       .long sys_times
-       .long sys_ni_syscall    /* old prof syscall holder */
-       .long sys_brk           /* 45 */
-       .long sys_setgid16
-       .long sys_getgid16
-       .long sys_signal
-       .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
-       .long sys_acct
-       .long sys_umount        /* recycled never used phys() */
-       .long sys_ni_syscall    /* old lock syscall holder */
-       .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall    /* old mpx syscall holder */
-       .long sys_setpgid
-       .long sys_ni_syscall    /* old ulimit syscall holder */
-       .long sys_olduname
-       .long sys_umask         /* 60 */
-       .long sys_chroot
-       .long sys_ustat
-       .long sys_dup2
-       .long sys_getppid
-       .long sys_getpgrp       /* 65 */
-       .long sys_setsid
-       .long sys_sigaction
-       .long sys_sgetmask
-       .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
-       .long sys_setregid16
-       .long sys_sigsuspend
-       .long sys_sigpending
-       .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
-       .long sys_old_getrlimit
-       .long sys_getrusage
-       .long sys_gettimeofday
-       .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
-       .long sys_setgroups16
-       .long sys_old_select
-       .long sys_symlink
-       .long sys_lstat
-       .long sys_readlink      /* 85 */
-       .long sys_uselib
-       .long sys_swapon
-       .long sys_reboot
-       .long sys_old_readdir
-       .long sys_old_mmap      /* 90 */
-       .long sys_munmap
-       .long sys_truncate
-       .long sys_ftruncate
-       .long sys_fchmod
-       .long sys_fchown16      /* 95 */
-       .long sys_getpriority
-       .long sys_setpriority
-       .long sys_ni_syscall    /* old profil syscall holder */
-       .long sys_statfs
-       .long sys_fstatfs       /* 100 */
-       .long sys_ioperm
-       .long sys_socketcall
-       .long sys_syslog
-       .long sys_setitimer
-       .long sys_getitimer     /* 105 */
-       .long sys_newstat
-       .long sys_newlstat
-       .long sys_newfstat
-       .long sys_uname
-       .long ptregs_iopl       /* 110 */
-       .long sys_vhangup
-       .long sys_ni_syscall    /* old "idle" system call */
-       .long ptregs_vm86old
-       .long sys_wait4
-       .long sys_swapoff       /* 115 */
-       .long sys_sysinfo
-       .long sys_ipc
-       .long sys_fsync
-       .long ptregs_sigreturn
-       .long ptregs_clone      /* 120 */
-       .long sys_setdomainname
-       .long sys_newuname
-       .long sys_modify_ldt
-       .long sys_adjtimex
-       .long sys_mprotect      /* 125 */
-       .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "create_module" */
-       .long sys_init_module
-       .long sys_delete_module
-       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
-       .long sys_quotactl
-       .long sys_getpgid
-       .long sys_fchdir
-       .long sys_bdflush
-       .long sys_sysfs         /* 135 */
-       .long sys_personality
-       .long sys_ni_syscall    /* reserved for afs_syscall */
-       .long sys_setfsuid16
-       .long sys_setfsgid16
-       .long sys_llseek        /* 140 */
-       .long sys_getdents
-       .long sys_select
-       .long sys_flock
-       .long sys_msync
-       .long sys_readv         /* 145 */
-       .long sys_writev
-       .long sys_getsid
-       .long sys_fdatasync
-       .long sys_sysctl
-       .long sys_mlock         /* 150 */
-       .long sys_munlock
-       .long sys_mlockall
-       .long sys_munlockall
-       .long sys_sched_setparam
-       .long sys_sched_getparam   /* 155 */
-       .long sys_sched_setscheduler
-       .long sys_sched_getscheduler
-       .long sys_sched_yield
-       .long sys_sched_get_priority_max
-       .long sys_sched_get_priority_min  /* 160 */
-       .long sys_sched_rr_get_interval
-       .long sys_nanosleep
-       .long sys_mremap
-       .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long ptregs_vm86
-       .long sys_ni_syscall    /* Old sys_query_module */
-       .long sys_poll
-       .long sys_ni_syscall    /* Old nfsservctl */
-       .long sys_setresgid16   /* 170 */
-       .long sys_getresgid16
-       .long sys_prctl
-       .long ptregs_rt_sigreturn
-       .long sys_rt_sigaction
-       .long sys_rt_sigprocmask        /* 175 */
-       .long sys_rt_sigpending
-       .long sys_rt_sigtimedwait
-       .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend
-       .long sys_pread64       /* 180 */
-       .long sys_pwrite64
-       .long sys_chown16
-       .long sys_getcwd
-       .long sys_capget
-       .long sys_capset        /* 185 */
-       .long ptregs_sigaltstack
-       .long sys_sendfile
-       .long sys_ni_syscall    /* reserved for streams1 */
-       .long sys_ni_syscall    /* reserved for streams2 */
-       .long ptregs_vfork      /* 190 */
-       .long sys_getrlimit
-       .long sys_mmap_pgoff
-       .long sys_truncate64
-       .long sys_ftruncate64
-       .long sys_stat64        /* 195 */
-       .long sys_lstat64
-       .long sys_fstat64
-       .long sys_lchown
-       .long sys_getuid
-       .long sys_getgid        /* 200 */
-       .long sys_geteuid
-       .long sys_getegid
-       .long sys_setreuid
-       .long sys_setregid
-       .long sys_getgroups     /* 205 */
-       .long sys_setgroups
-       .long sys_fchown
-       .long sys_setresuid
-       .long sys_getresuid
-       .long sys_setresgid     /* 210 */
-       .long sys_getresgid
-       .long sys_chown
-       .long sys_setuid
-       .long sys_setgid
-       .long sys_setfsuid      /* 215 */
-       .long sys_setfsgid
-       .long sys_pivot_root
-       .long sys_mincore
-       .long sys_madvise
-       .long sys_getdents64    /* 220 */
-       .long sys_fcntl64
-       .long sys_ni_syscall    /* reserved for TUX */
-       .long sys_ni_syscall
-       .long sys_gettid
-       .long sys_readahead     /* 225 */
-       .long sys_setxattr
-       .long sys_lsetxattr
-       .long sys_fsetxattr
-       .long sys_getxattr
-       .long sys_lgetxattr     /* 230 */
-       .long sys_fgetxattr
-       .long sys_listxattr
-       .long sys_llistxattr
-       .long sys_flistxattr
-       .long sys_removexattr   /* 235 */
-       .long sys_lremovexattr
-       .long sys_fremovexattr
-       .long sys_tkill
-       .long sys_sendfile64
-       .long sys_futex         /* 240 */
-       .long sys_sched_setaffinity
-       .long sys_sched_getaffinity
-       .long sys_set_thread_area
-       .long sys_get_thread_area
-       .long sys_io_setup      /* 245 */
-       .long sys_io_destroy
-       .long sys_io_getevents
-       .long sys_io_submit
-       .long sys_io_cancel
-       .long sys_fadvise64     /* 250 */
-       .long sys_ni_syscall
-       .long sys_exit_group
-       .long sys_lookup_dcookie
-       .long sys_epoll_create
-       .long sys_epoll_ctl     /* 255 */
-       .long sys_epoll_wait
-       .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime         /* 260 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime         /* 265 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
-       .long sys_statfs64
-       .long sys_fstatfs64
-       .long sys_tgkill        /* 270 */
-       .long sys_utimes
-       .long sys_fadvise64_64
-       .long sys_ni_syscall    /* sys_vserver */
-       .long sys_mbind
-       .long sys_get_mempolicy
-       .long sys_set_mempolicy
-       .long sys_mq_open
-       .long sys_mq_unlink
-       .long sys_mq_timedsend
-       .long sys_mq_timedreceive       /* 280 */
-       .long sys_mq_notify
-       .long sys_mq_getsetattr
-       .long sys_kexec_load
-       .long sys_waitid
-       .long sys_ni_syscall            /* 285 */ /* available */
-       .long sys_add_key
-       .long sys_request_key
-       .long sys_keyctl
-       .long sys_ioprio_set
-       .long sys_ioprio_get            /* 290 */
-       .long sys_inotify_init
-       .long sys_inotify_add_watch
-       .long sys_inotify_rm_watch
-       .long sys_migrate_pages
-       .long sys_openat                /* 295 */
-       .long sys_mkdirat
-       .long sys_mknodat
-       .long sys_fchownat
-       .long sys_futimesat
-       .long sys_fstatat64             /* 300 */
-       .long sys_unlinkat
-       .long sys_renameat
-       .long sys_linkat
-       .long sys_symlinkat
-       .long sys_readlinkat            /* 305 */
-       .long sys_fchmodat
-       .long sys_faccessat
-       .long sys_pselect6
-       .long sys_ppoll
-       .long sys_unshare               /* 310 */
-       .long sys_set_robust_list
-       .long sys_get_robust_list
-       .long sys_splice
-       .long sys_sync_file_range
-       .long sys_tee                   /* 315 */
-       .long sys_vmsplice
-       .long sys_move_pages
-       .long sys_getcpu
-       .long sys_epoll_pwait
-       .long sys_utimensat             /* 320 */
-       .long sys_signalfd
-       .long sys_timerfd_create
-       .long sys_eventfd
-       .long sys_fallocate
-       .long sys_timerfd_settime       /* 325 */
-       .long sys_timerfd_gettime
-       .long sys_signalfd4
-       .long sys_eventfd2
-       .long sys_epoll_create1
-       .long sys_dup3                  /* 330 */
-       .long sys_pipe2
-       .long sys_inotify_init1
-       .long sys_preadv
-       .long sys_pwritev
-       .long sys_rt_tgsigqueueinfo     /* 335 */
-       .long sys_perf_event_open
-       .long sys_recvmmsg
-       .long sys_fanotify_init
-       .long sys_fanotify_mark
-       .long sys_prlimit64             /* 340 */
-       .long sys_name_to_handle_at
-       .long sys_open_by_handle_at
-       .long sys_clock_adjtime
-       .long sys_syncfs
-       .long sys_sendmmsg              /* 345 */
-       .long sys_setns
-       .long sys_process_vm_readv
-       .long sys_process_vm_writev
diff --git a/arch/x86/syscalls/Makefile b/arch/x86/syscalls/Makefile
new file mode 100644 (file)
index 0000000..564b247
--- /dev/null
@@ -0,0 +1,43 @@
+out := $(obj)/../include/generated/asm
+
+# Create output directory if not already present
+_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
+
+syscall32 := $(srctree)/$(src)/syscall_32.tbl
+syscall64 := $(srctree)/$(src)/syscall_64.tbl
+
+syshdr := $(srctree)/$(src)/syscallhdr.sh
+systbl := $(srctree)/$(src)/syscalltbl.sh
+
+quiet_cmd_syshdr = SYSHDR  $@
+      cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' $< $@ \
+                  $(syshdr_abi_$(basetarget)) $(syshdr_pfx_$(basetarget))
+quiet_cmd_systbl = SYSTBL  $@
+      cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@
+
+syshdr_abi_unistd_32 := i386
+$(out)/unistd_32.h: $(syscall32) $(syshdr)
+       $(call if_changed,syshdr)
+
+syshdr_abi_unistd_32_ia32 := i386
+syshdr_pfx_unistd_32_ia32 := ia32_
+$(out)/unistd_32_ia32.h: $(syscall32) $(syshdr)
+       $(call if_changed,syshdr)
+
+syshdr_abi_unistd_64 := 64
+$(out)/unistd_64.h: $(syscall64) $(syshdr)
+       $(call if_changed,syshdr)
+
+$(out)/syscalls_32.h: $(syscall32) $(systbl)
+       $(call if_changed,systbl)
+$(out)/syscalls_64.h: $(syscall64) $(systbl)
+       $(call if_changed,systbl)
+
+syshdr-y                       += unistd_32.h unistd_64.h
+syshdr-y                       += syscalls_32.h
+syshdr-$(CONFIG_X86_64)                += unistd_32_ia32.h
+syshdr-$(CONFIG_X86_64)                += syscalls_64.h
+
+targets        += $(syshdr-y)
+
+all: $(addprefix $(out)/,$(targets))
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
new file mode 100644 (file)
index 0000000..ce98e28
--- /dev/null
@@ -0,0 +1,357 @@
+#
+# 32-bit system call numbers and entry vectors
+#
+# The format is:
+# <number> <abi> <name> <entry point> <compat entry point>
+#
+# The abi is always "i386" for this file.
+#
+0      i386    restart_syscall         sys_restart_syscall
+1      i386    exit                    sys_exit
+2      i386    fork                    ptregs_fork                     stub32_fork
+3      i386    read                    sys_read
+4      i386    write                   sys_write
+5      i386    open                    sys_open                        compat_sys_open
+6      i386    close                   sys_close
+7      i386    waitpid                 sys_waitpid                     sys32_waitpid
+8      i386    creat                   sys_creat
+9      i386    link                    sys_link
+10     i386    unlink                  sys_unlink
+11     i386    execve                  ptregs_execve                   stub32_execve
+12     i386    chdir                   sys_chdir
+13     i386    time                    sys_time                        compat_sys_time
+14     i386    mknod                   sys_mknod
+15     i386    chmod                   sys_chmod
+16     i386    lchown                  sys_lchown16
+17     i386    break
+18     i386    oldstat                 sys_stat
+19     i386    lseek                   sys_lseek                       sys32_lseek
+20     i386    getpid                  sys_getpid
+21     i386    mount                   sys_mount                       compat_sys_mount
+22     i386    umount                  sys_oldumount
+23     i386    setuid                  sys_setuid16
+24     i386    getuid                  sys_getuid16
+25     i386    stime                   sys_stime                       compat_sys_stime
+26     i386    ptrace                  sys_ptrace                      compat_sys_ptrace
+27     i386    alarm                   sys_alarm
+28     i386    oldfstat                sys_fstat
+29     i386    pause                   sys_pause
+30     i386    utime                   sys_utime                       compat_sys_utime
+31     i386    stty
+32     i386    gtty
+33     i386    access                  sys_access
+34     i386    nice                    sys_nice
+35     i386    ftime
+36     i386    sync                    sys_sync
+37     i386    kill                    sys_kill                        sys32_kill
+38     i386    rename                  sys_rename
+39     i386    mkdir                   sys_mkdir
+40     i386    rmdir                   sys_rmdir
+41     i386    dup                     sys_dup
+42     i386    pipe                    sys_pipe
+43     i386    times                   sys_times                       compat_sys_times
+44     i386    prof
+45     i386    brk                     sys_brk
+46     i386    setgid                  sys_setgid16
+47     i386    getgid                  sys_getgid16
+48     i386    signal                  sys_signal
+49     i386    geteuid                 sys_geteuid16
+50     i386    getegid                 sys_getegid16
+51     i386    acct                    sys_acct
+52     i386    umount2                 sys_umount
+53     i386    lock
+54     i386    ioctl                   sys_ioctl                       compat_sys_ioctl
+55     i386    fcntl                   sys_fcntl                       compat_sys_fcntl64
+56     i386    mpx
+57     i386    setpgid                 sys_setpgid
+58     i386    ulimit
+59     i386    oldolduname             sys_olduname
+60     i386    umask                   sys_umask
+61     i386    chroot                  sys_chroot
+62     i386    ustat                   sys_ustat                       compat_sys_ustat
+63     i386    dup2                    sys_dup2
+64     i386    getppid                 sys_getppid
+65     i386    getpgrp                 sys_getpgrp
+66     i386    setsid                  sys_setsid
+67     i386    sigaction               sys_sigaction                   sys32_sigaction
+68     i386    sgetmask                sys_sgetmask
+69     i386    ssetmask                sys_ssetmask
+70     i386    setreuid                sys_setreuid16
+71     i386    setregid                sys_setregid16
+72     i386    sigsuspend              sys_sigsuspend                  sys32_sigsuspend
+73     i386    sigpending              sys_sigpending                  compat_sys_sigpending
+74     i386    sethostname             sys_sethostname
+75     i386    setrlimit               sys_setrlimit                   compat_sys_setrlimit
+76     i386    getrlimit               sys_old_getrlimit               compat_sys_old_getrlimit
+77     i386    getrusage               sys_getrusage                   compat_sys_getrusage
+78     i386    gettimeofday            sys_gettimeofday                compat_sys_gettimeofday
+79     i386    settimeofday            sys_settimeofday                compat_sys_settimeofday
+80     i386    getgroups               sys_getgroups16
+81     i386    setgroups               sys_setgroups16
+82     i386    select                  sys_old_select                  compat_sys_old_select
+83     i386    symlink                 sys_symlink
+84     i386    oldlstat                sys_lstat
+85     i386    readlink                sys_readlink
+86     i386    uselib                  sys_uselib
+87     i386    swapon                  sys_swapon
+88     i386    reboot                  sys_reboot
+89     i386    readdir                 sys_old_readdir                 compat_sys_old_readdir
+90     i386    mmap                    sys_old_mmap                    sys32_mmap
+91     i386    munmap                  sys_munmap
+92     i386    truncate                sys_truncate
+93     i386    ftruncate               sys_ftruncate
+94     i386    fchmod                  sys_fchmod
+95     i386    fchown                  sys_fchown16
+96     i386    getpriority             sys_getpriority
+97     i386    setpriority             sys_setpriority
+98     i386    profil
+99     i386    statfs                  sys_statfs                      compat_sys_statfs
+100    i386    fstatfs                 sys_fstatfs                     compat_sys_fstatfs
+101    i386    ioperm                  sys_ioperm
+102    i386    socketcall              sys_socketcall                  compat_sys_socketcall
+103    i386    syslog                  sys_syslog
+104    i386    setitimer               sys_setitimer                   compat_sys_setitimer
+105    i386    getitimer               sys_getitimer                   compat_sys_getitimer
+106    i386    stat                    sys_newstat                     compat_sys_newstat
+107    i386    lstat                   sys_newlstat                    compat_sys_newlstat
+108    i386    fstat                   sys_newfstat                    compat_sys_newfstat
+109    i386    olduname                sys_uname
+110    i386    iopl                    ptregs_iopl                     stub32_iopl
+111    i386    vhangup                 sys_vhangup
+112    i386    idle
+113    i386    vm86old                 ptregs_vm86old                  sys32_vm86_warning
+114    i386    wait4                   sys_wait4                       compat_sys_wait4
+115    i386    swapoff                 sys_swapoff
+116    i386    sysinfo                 sys_sysinfo                     compat_sys_sysinfo
+117    i386    ipc                     sys_ipc                         sys32_ipc
+118    i386    fsync                   sys_fsync
+119    i386    sigreturn               ptregs_sigreturn                stub32_sigreturn
+120    i386    clone                   ptregs_clone                    stub32_clone
+121    i386    setdomainname           sys_setdomainname
+122    i386    uname                   sys_newuname
+123    i386    modify_ldt              sys_modify_ldt
+124    i386    adjtimex                sys_adjtimex                    compat_sys_adjtimex
+125    i386    mprotect                sys_mprotect                    sys32_mprotect
+126    i386    sigprocmask             sys_sigprocmask                 compat_sys_sigprocmask
+127    i386    create_module
+128    i386    init_module             sys_init_module
+129    i386    delete_module           sys_delete_module
+130    i386    get_kernel_syms
+131    i386    quotactl                sys_quotactl                    sys32_quotactl
+132    i386    getpgid                 sys_getpgid
+133    i386    fchdir                  sys_fchdir
+134    i386    bdflush                 sys_bdflush
+135    i386    sysfs                   sys_sysfs
+136    i386    personality             sys_personality
+137    i386    afs_syscall
+138    i386    setfsuid                sys_setfsuid16
+139    i386    setfsgid                sys_setfsgid16
+140    i386    _llseek                 sys_llseek
+141    i386    getdents                sys_getdents                    compat_sys_getdents
+142    i386    _newselect              sys_select                      compat_sys_select
+143    i386    flock                   sys_flock
+144    i386    msync                   sys_msync
+145    i386    readv                   sys_readv                       compat_sys_readv
+146    i386    writev                  sys_writev                      compat_sys_writev
+147    i386    getsid                  sys_getsid
+148    i386    fdatasync               sys_fdatasync
+149    i386    _sysctl                 sys_sysctl                      compat_sys_sysctl
+150    i386    mlock                   sys_mlock
+151    i386    munlock                 sys_munlock
+152    i386    mlockall                sys_mlockall
+153    i386    munlockall              sys_munlockall
+154    i386    sched_setparam          sys_sched_setparam
+155    i386    sched_getparam          sys_sched_getparam
+156    i386    sched_setscheduler      sys_sched_setscheduler
+157    i386    sched_getscheduler      sys_sched_getscheduler
+158    i386    sched_yield             sys_sched_yield
+159    i386    sched_get_priority_max  sys_sched_get_priority_max
+160    i386    sched_get_priority_min  sys_sched_get_priority_min
+161    i386    sched_rr_get_interval   sys_sched_rr_get_interval       sys32_sched_rr_get_interval
+162    i386    nanosleep               sys_nanosleep                   compat_sys_nanosleep
+163    i386    mremap                  sys_mremap
+164    i386    setresuid               sys_setresuid16
+165    i386    getresuid               sys_getresuid16
+166    i386    vm86                    ptregs_vm86                     sys32_vm86_warning
+167    i386    query_module
+168    i386    poll                    sys_poll
+169    i386    nfsservctl
+170    i386    setresgid               sys_setresgid16
+171    i386    getresgid               sys_getresgid16
+172    i386    prctl                   sys_prctl
+173    i386    rt_sigreturn            ptregs_rt_sigreturn             stub32_rt_sigreturn
+174    i386    rt_sigaction            sys_rt_sigaction                sys32_rt_sigaction
+175    i386    rt_sigprocmask          sys_rt_sigprocmask              sys32_rt_sigprocmask
+176    i386    rt_sigpending           sys_rt_sigpending               sys32_rt_sigpending
+177    i386    rt_sigtimedwait         sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait
+178    i386    rt_sigqueueinfo         sys_rt_sigqueueinfo             sys32_rt_sigqueueinfo
+179    i386    rt_sigsuspend           sys_rt_sigsuspend
+180    i386    pread64                 sys_pread64                     sys32_pread
+181    i386    pwrite64                sys_pwrite64                    sys32_pwrite
+182    i386    chown                   sys_chown16
+183    i386    getcwd                  sys_getcwd
+184    i386    capget                  sys_capget
+185    i386    capset                  sys_capset
+186    i386    sigaltstack             ptregs_sigaltstack              stub32_sigaltstack
+187    i386    sendfile                sys_sendfile                    sys32_sendfile
+188    i386    getpmsg
+189    i386    putpmsg
+190    i386    vfork                   ptregs_vfork                    stub32_vfork
+191    i386    ugetrlimit              sys_getrlimit                   compat_sys_getrlimit
+192    i386    mmap2                   sys_mmap_pgoff
+193    i386    truncate64              sys_truncate64                  sys32_truncate64
+194    i386    ftruncate64             sys_ftruncate64                 sys32_ftruncate64
+195    i386    stat64                  sys_stat64                      sys32_stat64
+196    i386    lstat64                 sys_lstat64                     sys32_lstat64
+197    i386    fstat64                 sys_fstat64                     sys32_fstat64
+198    i386    lchown32                sys_lchown
+199    i386    getuid32                sys_getuid
+200    i386    getgid32                sys_getgid
+201    i386    geteuid32               sys_geteuid
+202    i386    getegid32               sys_getegid
+203    i386    setreuid32              sys_setreuid
+204    i386    setregid32              sys_setregid
+205    i386    getgroups32             sys_getgroups
+206    i386    setgroups32             sys_setgroups
+207    i386    fchown32                sys_fchown
+208    i386    setresuid32             sys_setresuid
+209    i386    getresuid32             sys_getresuid
+210    i386    setresgid32             sys_setresgid
+211    i386    getresgid32             sys_getresgid
+212    i386    chown32                 sys_chown
+213    i386    setuid32                sys_setuid
+214    i386    setgid32                sys_setgid
+215    i386    setfsuid32              sys_setfsuid
+216    i386    setfsgid32              sys_setfsgid
+217    i386    pivot_root              sys_pivot_root
+218    i386    mincore                 sys_mincore
+219    i386    madvise                 sys_madvise
+220    i386    getdents64              sys_getdents64                  compat_sys_getdents64
+221    i386    fcntl64                 sys_fcntl64                     compat_sys_fcntl64
+# 222 is unused
+# 223 is unused
+224    i386    gettid                  sys_gettid
+225    i386    readahead               sys_readahead                   sys32_readahead
+226    i386    setxattr                sys_setxattr
+227    i386    lsetxattr               sys_lsetxattr
+228    i386    fsetxattr               sys_fsetxattr
+229    i386    getxattr                sys_getxattr
+230    i386    lgetxattr               sys_lgetxattr
+231    i386    fgetxattr               sys_fgetxattr
+232    i386    listxattr               sys_listxattr
+233    i386    llistxattr              sys_llistxattr
+234    i386    flistxattr              sys_flistxattr
+235    i386    removexattr             sys_removexattr
+236    i386    lremovexattr            sys_lremovexattr
+237    i386    fremovexattr            sys_fremovexattr
+238    i386    tkill                   sys_tkill
+239    i386    sendfile64              sys_sendfile64
+240    i386    futex                   sys_futex                       compat_sys_futex
+241    i386    sched_setaffinity       sys_sched_setaffinity           compat_sys_sched_setaffinity
+242    i386    sched_getaffinity       sys_sched_getaffinity           compat_sys_sched_getaffinity
+243    i386    set_thread_area         sys_set_thread_area
+244    i386    get_thread_area         sys_get_thread_area
+245    i386    io_setup                sys_io_setup                    compat_sys_io_setup
+246    i386    io_destroy              sys_io_destroy
+247    i386    io_getevents            sys_io_getevents                compat_sys_io_getevents
+248    i386    io_submit               sys_io_submit                   compat_sys_io_submit
+249    i386    io_cancel               sys_io_cancel
+250    i386    fadvise64               sys_fadvise64                   sys32_fadvise64
+# 251 is available for reuse (was briefly sys_set_zone_reclaim)
+252    i386    exit_group              sys_exit_group
+253    i386    lookup_dcookie          sys_lookup_dcookie              sys32_lookup_dcookie
+254    i386    epoll_create            sys_epoll_create
+255    i386    epoll_ctl               sys_epoll_ctl
+256    i386    epoll_wait              sys_epoll_wait
+257    i386    remap_file_pages        sys_remap_file_pages
+258    i386    set_tid_address         sys_set_tid_address
+259    i386    timer_create            sys_timer_create                compat_sys_timer_create
+260    i386    timer_settime           sys_timer_settime               compat_sys_timer_settime
+261    i386    timer_gettime           sys_timer_gettime               compat_sys_timer_gettime
+262    i386    timer_getoverrun        sys_timer_getoverrun
+263    i386    timer_delete            sys_timer_delete
+264    i386    clock_settime           sys_clock_settime               compat_sys_clock_settime
+265    i386    clock_gettime           sys_clock_gettime               compat_sys_clock_gettime
+266    i386    clock_getres            sys_clock_getres                compat_sys_clock_getres
+267    i386    clock_nanosleep         sys_clock_nanosleep             compat_sys_clock_nanosleep
+268    i386    statfs64                sys_statfs64                    compat_sys_statfs64
+269    i386    fstatfs64               sys_fstatfs64                   compat_sys_fstatfs64
+270    i386    tgkill                  sys_tgkill
+271    i386    utimes                  sys_utimes                      compat_sys_utimes
+272    i386    fadvise64_64            sys_fadvise64_64                sys32_fadvise64_64
+273    i386    vserver
+274    i386    mbind                   sys_mbind
+275    i386    get_mempolicy           sys_get_mempolicy               compat_sys_get_mempolicy
+276    i386    set_mempolicy           sys_set_mempolicy
+277    i386    mq_open                 sys_mq_open                     compat_sys_mq_open
+278    i386    mq_unlink               sys_mq_unlink
+279    i386    mq_timedsend            sys_mq_timedsend                compat_sys_mq_timedsend
+280    i386    mq_timedreceive         sys_mq_timedreceive             compat_sys_mq_timedreceive
+281    i386    mq_notify               sys_mq_notify                   compat_sys_mq_notify
+282    i386    mq_getsetaddr           sys_mq_getsetattr               compat_sys_mq_getsetattr
+283    i386    kexec_load              sys_kexec_load                  compat_sys_kexec_load
+284    i386    waitid                  sys_waitid                      compat_sys_waitid
+# 285 sys_setaltroot
+286    i386    add_key                 sys_add_key
+287    i386    request_key             sys_request_key
+288    i386    keyctl                  sys_keyctl
+289    i386    ioprio_set              sys_ioprio_set
+290    i386    ioprio_get              sys_ioprio_get
+291    i386    inotify_init            sys_inotify_init
+292    i386    inotify_add_watch       sys_inotify_add_watch
+293    i386    inotify_rm_watch        sys_inotify_rm_watch
+294    i386    migrate_pages           sys_migrate_pages
+295    i386    openat                  sys_openat                      compat_sys_openat
+296    i386    mkdirat                 sys_mkdirat
+297    i386    mknodat                 sys_mknodat
+298    i386    fchownat                sys_fchownat
+299    i386    futimesat               sys_futimesat                   compat_sys_futimesat
+300    i386    fstatat64               sys_fstatat64                   sys32_fstatat
+301    i386    unlinkat                sys_unlinkat
+302    i386    renameat                sys_renameat
+303    i386    linkat                  sys_linkat
+304    i386    symlinkat               sys_symlinkat
+305    i386    readlinkat              sys_readlinkat
+306    i386    fchmodat                sys_fchmodat
+307    i386    faccessat               sys_faccessat
+308    i386    pselect6                sys_pselect6                    compat_sys_pselect6
+309    i386    ppoll                   sys_ppoll                       compat_sys_ppoll
+310    i386    unshare                 sys_unshare
+311    i386    set_robust_list         sys_set_robust_list             compat_sys_set_robust_list
+312    i386    get_robust_list         sys_get_robust_list             compat_sys_get_robust_list
+313    i386    splice                  sys_splice
+314    i386    sync_file_range         sys_sync_file_range             sys32_sync_file_range
+315    i386    tee                     sys_tee
+316    i386    vmsplice                sys_vmsplice                    compat_sys_vmsplice
+317    i386    move_pages              sys_move_pages                  compat_sys_move_pages
+318    i386    getcpu                  sys_getcpu
+319    i386    epoll_pwait             sys_epoll_pwait
+320    i386    utimensat               sys_utimensat                   compat_sys_utimensat
+321    i386    signalfd                sys_signalfd                    compat_sys_signalfd
+322    i386    timerfd_create          sys_timerfd_create
+323    i386    eventfd                 sys_eventfd
+324    i386    fallocate               sys_fallocate                   sys32_fallocate
+325    i386    timerfd_settime         sys_timerfd_settime             compat_sys_timerfd_settime
+326    i386    timerfd_gettime         sys_timerfd_gettime             compat_sys_timerfd_gettime
+327    i386    signalfd4               sys_signalfd4                   compat_sys_signalfd4
+328    i386    eventfd2                sys_eventfd2
+329    i386    epoll_create1           sys_epoll_create1
+330    i386    dup3                    sys_dup3
+331    i386    pipe2                   sys_pipe2
+332    i386    inotify_init1           sys_inotify_init1
+333    i386    preadv                  sys_preadv                      compat_sys_preadv
+334    i386    pwritev                 sys_pwritev                     compat_sys_pwritev
+335    i386    rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo
+336    i386    perf_event_open         sys_perf_event_open
+337    i386    recvmmsg                sys_recvmmsg                    compat_sys_recvmmsg
+338    i386    fanotify_init           sys_fanotify_init
+339    i386    fanotify_mark           sys_fanotify_mark               sys32_fanotify_mark
+340    i386    prlimit64               sys_prlimit64
+341    i386    name_to_handle_at       sys_name_to_handle_at
+342    i386    open_by_handle_at       sys_open_by_handle_at           compat_sys_open_by_handle_at
+343    i386    clock_adjtime           sys_clock_adjtime               compat_sys_clock_adjtime
+344    i386    syncfs                  sys_syncfs
+345    i386    sendmmsg                sys_sendmmsg                    compat_sys_sendmmsg
+346    i386    setns                   sys_setns
+347    i386    process_vm_readv        sys_process_vm_readv            compat_sys_process_vm_readv
+348    i386    process_vm_writev       sys_process_vm_writev           compat_sys_process_vm_writev
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
new file mode 100644 (file)
index 0000000..b440a8f
--- /dev/null
@@ -0,0 +1,320 @@
+#
+# 64-bit system call numbers and entry vectors
+#
+# The format is:
+# <number> <abi> <name> <entry point>
+#
+# The abi is always "64" for this file (for now.)
+#
+0      64      read                    sys_read
+1      64      write                   sys_write
+2      64      open                    sys_open
+3      64      close                   sys_close
+4      64      stat                    sys_newstat
+5      64      fstat                   sys_newfstat
+6      64      lstat                   sys_newlstat
+7      64      poll                    sys_poll
+8      64      lseek                   sys_lseek
+9      64      mmap                    sys_mmap
+10     64      mprotect                sys_mprotect
+11     64      munmap                  sys_munmap
+12     64      brk                     sys_brk
+13     64      rt_sigaction            sys_rt_sigaction
+14     64      rt_sigprocmask          sys_rt_sigprocmask
+15     64      rt_sigreturn            stub_rt_sigreturn
+16     64      ioctl                   sys_ioctl
+17     64      pread64                 sys_pread64
+18     64      pwrite64                sys_pwrite64
+19     64      readv                   sys_readv
+20     64      writev                  sys_writev
+21     64      access                  sys_access
+22     64      pipe                    sys_pipe
+23     64      select                  sys_select
+24     64      sched_yield             sys_sched_yield
+25     64      mremap                  sys_mremap
+26     64      msync                   sys_msync
+27     64      mincore                 sys_mincore
+28     64      madvise                 sys_madvise
+29     64      shmget                  sys_shmget
+30     64      shmat                   sys_shmat
+31     64      shmctl                  sys_shmctl
+32     64      dup                     sys_dup
+33     64      dup2                    sys_dup2
+34     64      pause                   sys_pause
+35     64      nanosleep               sys_nanosleep
+36     64      getitimer               sys_getitimer
+37     64      alarm                   sys_alarm
+38     64      setitimer               sys_setitimer
+39     64      getpid                  sys_getpid
+40     64      sendfile                sys_sendfile64
+41     64      socket                  sys_socket
+42     64      connect                 sys_connect
+43     64      accept                  sys_accept
+44     64      sendto                  sys_sendto
+45     64      recvfrom                sys_recvfrom
+46     64      sendmsg                 sys_sendmsg
+47     64      recvmsg                 sys_recvmsg
+48     64      shutdown                sys_shutdown
+49     64      bind                    sys_bind
+50     64      listen                  sys_listen
+51     64      getsockname             sys_getsockname
+52     64      getpeername             sys_getpeername
+53     64      socketpair              sys_socketpair
+54     64      setsockopt              sys_setsockopt
+55     64      getsockopt              sys_getsockopt
+56     64      clone                   stub_clone
+57     64      fork                    stub_fork
+58     64      vfork                   stub_vfork
+59     64      execve                  stub_execve
+60     64      exit                    sys_exit
+61     64      wait4                   sys_wait4
+62     64      kill                    sys_kill
+63     64      uname                   sys_newuname
+64     64      semget                  sys_semget
+65     64      semop                   sys_semop
+66     64      semctl                  sys_semctl
+67     64      shmdt                   sys_shmdt
+68     64      msgget                  sys_msgget
+69     64      msgsnd                  sys_msgsnd
+70     64      msgrcv                  sys_msgrcv
+71     64      msgctl                  sys_msgctl
+72     64      fcntl                   sys_fcntl
+73     64      flock                   sys_flock
+74     64      fsync                   sys_fsync
+75     64      fdatasync               sys_fdatasync
+76     64      truncate                sys_truncate
+77     64      ftruncate               sys_ftruncate
+78     64      getdents                sys_getdents
+79     64      getcwd                  sys_getcwd
+80     64      chdir                   sys_chdir
+81     64      fchdir                  sys_fchdir
+82     64      rename                  sys_rename
+83     64      mkdir                   sys_mkdir
+84     64      rmdir                   sys_rmdir
+85     64      creat                   sys_creat
+86     64      link                    sys_link
+87     64      unlink                  sys_unlink
+88     64      symlink                 sys_symlink
+89     64      readlink                sys_readlink
+90     64      chmod                   sys_chmod
+91     64      fchmod                  sys_fchmod
+92     64      chown                   sys_chown
+93     64      fchown                  sys_fchown
+94     64      lchown                  sys_lchown
+95     64      umask                   sys_umask
+96     64      gettimeofday            sys_gettimeofday
+97     64      getrlimit               sys_getrlimit
+98     64      getrusage               sys_getrusage
+99     64      sysinfo                 sys_sysinfo
+100    64      times                   sys_times
+101    64      ptrace                  sys_ptrace
+102    64      getuid                  sys_getuid
+103    64      syslog                  sys_syslog
+104    64      getgid                  sys_getgid
+105    64      setuid                  sys_setuid
+106    64      setgid                  sys_setgid
+107    64      geteuid                 sys_geteuid
+108    64      getegid                 sys_getegid
+109    64      setpgid                 sys_setpgid
+110    64      getppid                 sys_getppid
+111    64      getpgrp                 sys_getpgrp
+112    64      setsid                  sys_setsid
+113    64      setreuid                sys_setreuid
+114    64      setregid                sys_setregid
+115    64      getgroups               sys_getgroups
+116    64      setgroups               sys_setgroups
+117    64      setresuid               sys_setresuid
+118    64      getresuid               sys_getresuid
+119    64      setresgid               sys_setresgid
+120    64      getresgid               sys_getresgid
+121    64      getpgid                 sys_getpgid
+122    64      setfsuid                sys_setfsuid
+123    64      setfsgid                sys_setfsgid
+124    64      getsid                  sys_getsid
+125    64      capget                  sys_capget
+126    64      capset                  sys_capset
+127    64      rt_sigpending           sys_rt_sigpending
+128    64      rt_sigtimedwait         sys_rt_sigtimedwait
+129    64      rt_sigqueueinfo         sys_rt_sigqueueinfo
+130    64      rt_sigsuspend           sys_rt_sigsuspend
+131    64      sigaltstack             stub_sigaltstack
+132    64      utime                   sys_utime
+133    64      mknod                   sys_mknod
+134    64      uselib
+135    64      personality             sys_personality
+136    64      ustat                   sys_ustat
+137    64      statfs                  sys_statfs
+138    64      fstatfs                 sys_fstatfs
+139    64      sysfs                   sys_sysfs
+140    64      getpriority             sys_getpriority
+141    64      setpriority             sys_setpriority
+142    64      sched_setparam          sys_sched_setparam
+143    64      sched_getparam          sys_sched_getparam
+144    64      sched_setscheduler      sys_sched_setscheduler
+145    64      sched_getscheduler      sys_sched_getscheduler
+146    64      sched_get_priority_max  sys_sched_get_priority_max
+147    64      sched_get_priority_min  sys_sched_get_priority_min
+148    64      sched_rr_get_interval   sys_sched_rr_get_interval
+149    64      mlock                   sys_mlock
+150    64      munlock                 sys_munlock
+151    64      mlockall                sys_mlockall
+152    64      munlockall              sys_munlockall
+153    64      vhangup                 sys_vhangup
+154    64      modify_ldt              sys_modify_ldt
+155    64      pivot_root              sys_pivot_root
+156    64      _sysctl                 sys_sysctl
+157    64      prctl                   sys_prctl
+158    64      arch_prctl              sys_arch_prctl
+159    64      adjtimex                sys_adjtimex
+160    64      setrlimit               sys_setrlimit
+161    64      chroot                  sys_chroot
+162    64      sync                    sys_sync
+163    64      acct                    sys_acct
+164    64      settimeofday            sys_settimeofday
+165    64      mount                   sys_mount
+166    64      umount2                 sys_umount
+167    64      swapon                  sys_swapon
+168    64      swapoff                 sys_swapoff
+169    64      reboot                  sys_reboot
+170    64      sethostname             sys_sethostname
+171    64      setdomainname           sys_setdomainname
+172    64      iopl                    stub_iopl
+173    64      ioperm                  sys_ioperm
+174    64      create_module
+175    64      init_module             sys_init_module
+176    64      delete_module           sys_delete_module
+177    64      get_kernel_syms
+178    64      query_module
+179    64      quotactl                sys_quotactl
+180    64      nfsservctl
+181    64      getpmsg
+182    64      putpmsg
+183    64      afs_syscall
+184    64      tuxcall
+185    64      security
+186    64      gettid                  sys_gettid
+187    64      readahead               sys_readahead
+188    64      setxattr                sys_setxattr
+189    64      lsetxattr               sys_lsetxattr
+190    64      fsetxattr               sys_fsetxattr
+191    64      getxattr                sys_getxattr
+192    64      lgetxattr               sys_lgetxattr
+193    64      fgetxattr               sys_fgetxattr
+194    64      listxattr               sys_listxattr
+195    64      llistxattr              sys_llistxattr
+196    64      flistxattr              sys_flistxattr
+197    64      removexattr             sys_removexattr
+198    64      lremovexattr            sys_lremovexattr
+199    64      fremovexattr            sys_fremovexattr
+200    64      tkill                   sys_tkill
+201    64      time                    sys_time
+202    64      futex                   sys_futex
+203    64      sched_setaffinity       sys_sched_setaffinity
+204    64      sched_getaffinity       sys_sched_getaffinity
+205    64      set_thread_area
+206    64      io_setup                sys_io_setup
+207    64      io_destroy              sys_io_destroy
+208    64      io_getevents            sys_io_getevents
+209    64      io_submit               sys_io_submit
+210    64      io_cancel               sys_io_cancel
+211    64      get_thread_area
+212    64      lookup_dcookie          sys_lookup_dcookie
+213    64      epoll_create            sys_epoll_create
+214    64      epoll_ctl_old
+215    64      epoll_wait_old
+216    64      remap_file_pages        sys_remap_file_pages
+217    64      getdents64              sys_getdents64
+218    64      set_tid_address         sys_set_tid_address
+219    64      restart_syscall         sys_restart_syscall
+220    64      semtimedop              sys_semtimedop
+221    64      fadvise64               sys_fadvise64
+222    64      timer_create            sys_timer_create
+223    64      timer_settime           sys_timer_settime
+224    64      timer_gettime           sys_timer_gettime
+225    64      timer_getoverrun        sys_timer_getoverrun
+226    64      timer_delete            sys_timer_delete
+227    64      clock_settime           sys_clock_settime
+228    64      clock_gettime           sys_clock_gettime
+229    64      clock_getres            sys_clock_getres
+230    64      clock_nanosleep         sys_clock_nanosleep
+231    64      exit_group              sys_exit_group
+232    64      epoll_wait              sys_epoll_wait
+233    64      epoll_ctl               sys_epoll_ctl
+234    64      tgkill                  sys_tgkill
+235    64      utimes                  sys_utimes
+236    64      vserver
+237    64      mbind                   sys_mbind
+238    64      set_mempolicy           sys_set_mempolicy
+239    64      get_mempolicy           sys_get_mempolicy
+240    64      mq_open                 sys_mq_open
+241    64      mq_unlink               sys_mq_unlink
+242    64      mq_timedsend            sys_mq_timedsend
+243    64      mq_timedreceive         sys_mq_timedreceive
+244    64      mq_notify               sys_mq_notify
+245    64      mq_getsetattr           sys_mq_getsetattr
+246    64      kexec_load              sys_kexec_load
+247    64      waitid                  sys_waitid
+248    64      add_key                 sys_add_key
+249    64      request_key             sys_request_key
+250    64      keyctl                  sys_keyctl
+251    64      ioprio_set              sys_ioprio_set
+252    64      ioprio_get              sys_ioprio_get
+253    64      inotify_init            sys_inotify_init
+254    64      inotify_add_watch       sys_inotify_add_watch
+255    64      inotify_rm_watch        sys_inotify_rm_watch
+256    64      migrate_pages           sys_migrate_pages
+257    64      openat                  sys_openat
+258    64      mkdirat                 sys_mkdirat
+259    64      mknodat                 sys_mknodat
+260    64      fchownat                sys_fchownat
+261    64      futimesat               sys_futimesat
+262    64      newfstatat              sys_newfstatat
+263    64      unlinkat                sys_unlinkat
+264    64      renameat                sys_renameat
+265    64      linkat                  sys_linkat
+266    64      symlinkat               sys_symlinkat
+267    64      readlinkat              sys_readlinkat
+268    64      fchmodat                sys_fchmodat
+269    64      faccessat               sys_faccessat
+270    64      pselect6                sys_pselect6
+271    64      ppoll                   sys_ppoll
+272    64      unshare                 sys_unshare
+273    64      set_robust_list         sys_set_robust_list
+274    64      get_robust_list         sys_get_robust_list
+275    64      splice                  sys_splice
+276    64      tee                     sys_tee
+277    64      sync_file_range         sys_sync_file_range
+278    64      vmsplice                sys_vmsplice
+279    64      move_pages              sys_move_pages
+280    64      utimensat               sys_utimensat
+281    64      epoll_pwait             sys_epoll_pwait
+282    64      signalfd                sys_signalfd
+283    64      timerfd_create          sys_timerfd_create
+284    64      eventfd                 sys_eventfd
+285    64      fallocate               sys_fallocate
+286    64      timerfd_settime         sys_timerfd_settime
+287    64      timerfd_gettime         sys_timerfd_gettime
+288    64      accept4                 sys_accept4
+289    64      signalfd4               sys_signalfd4
+290    64      eventfd2                sys_eventfd2
+291    64      epoll_create1           sys_epoll_create1
+292    64      dup3                    sys_dup3
+293    64      pipe2                   sys_pipe2
+294    64      inotify_init1           sys_inotify_init1
+295    64      preadv                  sys_preadv
+296    64      pwritev                 sys_pwritev
+297    64      rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo
+298    64      perf_event_open         sys_perf_event_open
+299    64      recvmmsg                sys_recvmmsg
+300    64      fanotify_init           sys_fanotify_init
+301    64      fanotify_mark           sys_fanotify_mark
+302    64      prlimit64               sys_prlimit64
+303    64      name_to_handle_at       sys_name_to_handle_at
+304    64      open_by_handle_at       sys_open_by_handle_at
+305    64      clock_adjtime           sys_clock_adjtime
+306    64      syncfs                  sys_syncfs
+307    64      sendmmsg                sys_sendmmsg
+308    64      setns                   sys_setns
+309    64      getcpu                  sys_getcpu
+310    64      process_vm_readv        sys_process_vm_readv
+311    64      process_vm_writev       sys_process_vm_writev
diff --git a/arch/x86/syscalls/syscallhdr.sh b/arch/x86/syscalls/syscallhdr.sh
new file mode 100644 (file)
index 0000000..31fd5f1
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+prefix="$4"
+offset="$5"
+
+fileguard=_ASM_X86_`basename "$out" | sed \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+    -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+    echo "#ifndef ${fileguard}"
+    echo "#define ${fileguard} 1"
+    echo ""
+
+    while read nr abi name entry ; do
+       if [ -z "$offset" ]; then
+           echo "#define __NR_${prefix}${name} $nr"
+       else
+           echo "#define __NR_${prefix}${name} ($offset + $nr)"
+        fi
+    done
+
+    echo ""
+    echo "#endif /* ${fileguard} */"
+) > "$out"
diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh
new file mode 100644 (file)
index 0000000..0e7f8ec
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+in="$1"
+out="$2"
+
+grep '^[0-9]' "$in" | sort -n | (
+    while read nr abi name entry compat; do
+       abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
+       if [ -n "$compat" ]; then
+           echo "__SYSCALL_${abi}($nr, $entry, $compat)"
+       elif [ -n "$entry" ]; then
+           echo "__SYSCALL_${abi}($nr, $entry, $entry)"
+       fi
+    done
+) > "$out"
index 8fb58400e4155b32cb8281f6bd0a53d4b6a8d253..5d065b2222d370e13dd161a6b66e96590b747739 100644 (file)
@@ -37,7 +37,8 @@ subarch-$(CONFIG_MODULES) += ../kernel/module.o
 USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
 
 extra-y += user-offsets.s
-$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS)
+$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
+       -Iarch/x86/include/generated
 
 UNPROFILE_OBJS := stub_segv.o
 CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
diff --git a/arch/x86/um/sys_call_table_32.S b/arch/x86/um/sys_call_table_32.S
deleted file mode 100644 (file)
index a7ca80d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <linux/linkage.h>
-/* Steal i386 syscall table for our purposes, but with some slight changes.*/
-
-#define sys_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-#define sys_vm86old sys_ni_syscall
-#define sys_vm86 sys_ni_syscall
-
-#define old_mmap sys_old_mmap
-
-#define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
-#define ptregs_iopl sys_iopl
-#define ptregs_vm86old sys_vm86old
-#define ptregs_clone sys_clone
-#define ptregs_vm86 sys_vm86
-#define ptregs_sigaltstack sys_sigaltstack
-#define ptregs_vfork sys_vfork
-
-.section .rodata,"a"
-
-#include "../kernel/syscall_table_32.S"
-
-ENTRY(syscall_table_size)
-.long .-sys_call_table
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
new file mode 100644 (file)
index 0000000..416bd40
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * System call table for UML/i386, copied from arch/x86/kernel/syscall_*.c
+ * with some changes for UML.
+ */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+#include <generated/user_constants.h>
+
+#define __NO_STUBS
+
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
+
+/* Not going to be implemented by UML, since we have no hardware. */
+#define sys_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+#define sys_vm86old sys_ni_syscall
+#define sys_vm86 sys_ni_syscall
+
+#define old_mmap sys_old_mmap
+
+#define ptregs_fork sys_fork
+#define ptregs_execve sys_execve
+#define ptregs_iopl sys_iopl
+#define ptregs_vm86old sys_vm86old
+#define ptregs_clone sys_clone
+#define ptregs_vm86 sys_vm86
+#define ptregs_sigaltstack sys_sigaltstack
+#define ptregs_vfork sys_vfork
+
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
+#include <asm/syscalls_32.h>
+
+#undef __SYSCALL_I386
+#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym,
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void sys_ni_syscall(void);
+
+const sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+       /*
+        * Smells like a compiler bug -- it doesn't work
+        * when the & below is removed.
+        */
+       [0 ... __NR_syscall_max] = &sys_ni_syscall,
+#include <asm/syscalls_32.h>
+};
+
+int syscall_table_size = sizeof(sys_call_table);
index 99522f78b16251e8cc222fcb96e1b56de153bba1..fe626c3ba01b280a6ddc9b2bc3fb894b7c504c3e 100644 (file)
@@ -1,11 +1,12 @@
 /*
- * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * System call table for UML/x86-64, copied from arch/x86/kernel/syscall_*.c
  * with some changes for UML.
  */
 
 #include <linux/linkage.h>
 #include <linux/sys.h>
 #include <linux/cache.h>
+#include <generated/user_constants.h>
 
 #define __NO_STUBS
 
 #define stub_sigaltstack sys_sigaltstack
 #define stub_rt_sigreturn sys_rt_sigreturn
 
-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_UNISTD_64_H
-#include "../../x86/include/asm/unistd_64.h"
+#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
+#include <asm/syscalls_64.h>
 
-#undef __SYSCALL
-#define __SYSCALL(nr, sym) [ nr ] = sym,
-#undef _ASM_X86_UNISTD_64_H
+#undef __SYSCALL_64
+#define __SYSCALL_64(nr, sym, compat) [ nr ] = sym,
 
 typedef void (*sys_call_ptr_t)(void);
 
 extern void sys_ni_syscall(void);
 
-/*
- * We used to have a trick here which made sure that holes in the
- * x86_64 table were filled in with sys_ni_syscall, but a comment in
- * unistd_64.h says that holes aren't allowed, so the trick was
- * removed.
- * The trick looked like this
- *     [0 ... UM_NR_syscall_max] = &sys_ni_syscall
- * before including unistd_64.h - the later initializations overwrote
- * the sys_ni_syscall filler.
- */
-
-sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
-#include <asm/unistd_64.h>
+const sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+       /*
+        * Smells like a compiler bug -- it doesn't work
+        * when the & below is removed.
+        */
+       [0 ... __NR_syscall_max] = &sys_ni_syscall,
+#include <asm/syscalls_64.h>
 };
 
 int syscall_table_size = sizeof(sys_call_table);
index ca49be8ddd0c7160821a4d4db06f18346f52b195..5edf4f4bbf531f2e3912a1068bf78f65de8cbcf8 100644 (file)
@@ -8,6 +8,18 @@
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
+#ifdef __i386__
+#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+static char syscalls[] = {
+#include <asm/syscalls_32.h>
+};
+#else
+#define __SYSCALL_64(nr, sym, compat) [nr] = 1,
+static char syscalls[] = {
+#include <asm/syscalls_64.h>
+};
+#endif
+
 #define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
@@ -77,4 +89,7 @@ void foo(void)
        DEFINE(UM_PROT_READ, PROT_READ);
        DEFINE(UM_PROT_WRITE, PROT_WRITE);
        DEFINE(UM_PROT_EXEC, PROT_EXEC);
+
+       DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+       DEFINE(NR_syscalls, sizeof(syscalls));
 }
index 92e6a9048065eb567f3d9c857e689c2b4667dd15..978bbf7ac6af03bb26eed17329d3a24f6bf5337e 100644 (file)
@@ -1429,6 +1429,8 @@ static int pm_genpd_default_restore_state(struct device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+
 /**
  * pm_genpd_default_suspend - Default "device suspend" for PM domians.
  * @dev: Device to handle.
@@ -1517,6 +1519,19 @@ static int pm_genpd_default_thaw(struct device *dev)
        return cb ? cb(dev) : pm_generic_thaw(dev);
 }
 
+#else /* !CONFIG_PM_SLEEP */
+
+#define pm_genpd_default_suspend       NULL
+#define pm_genpd_default_suspend_late  NULL
+#define pm_genpd_default_resume_early  NULL
+#define pm_genpd_default_resume                NULL
+#define pm_genpd_default_freeze                NULL
+#define pm_genpd_default_freeze_late   NULL
+#define pm_genpd_default_thaw_early    NULL
+#define pm_genpd_default_thaw          NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 /**
  * pm_genpd_init - Initialize a generic I/O PM domain object.
  * @genpd: PM domain object to initialize.
index 51527ee92d101018680cd5b633265105a2952df1..66a265bf5867d1b516a03f34e8e50946db4c1e3e 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/pm_qos.h>
 #include <linux/hrtimer.h>
 
+#ifdef CONFIG_PM_RUNTIME
+
 /**
  * default_stop_ok - Default PM domain governor routine for stopping devices.
  * @dev: Device to check.
@@ -137,16 +139,28 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
        return true;
 }
 
-struct dev_power_governor simple_qos_governor = {
-       .stop_ok = default_stop_ok,
-       .power_down_ok = default_power_down_ok,
-};
-
 static bool always_on_power_down_ok(struct dev_pm_domain *domain)
 {
        return false;
 }
 
+#else /* !CONFIG_PM_RUNTIME */
+
+bool default_stop_ok(struct device *dev)
+{
+       return false;
+}
+
+#define default_power_down_ok  NULL
+#define always_on_power_down_ok        NULL
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+struct dev_power_governor simple_qos_governor = {
+       .stop_ok = default_stop_ok,
+       .power_down_ok = default_power_down_ok,
+};
+
 /**
  * pm_genpd_gov_always_on - A governor implementing an always-on policy
  */
index 6f07ec1c2f58d2dabd766463165e32728910faf6..a30aa103f95b33a4567b519250331725dc5f9539 100644 (file)
@@ -116,6 +116,8 @@ config PARIDE
 
 source "drivers/block/paride/Kconfig"
 
+source "drivers/block/mtip32xx/Kconfig"
+
 config BLK_CPQ_DA
        tristate "Compaq SMART2 support"
        depends on PCI && VIRT_TO_BUS
index 76646e9a1c91528617c22e2c3f429201531acdf4..ad7b74a44ef3dd3e1e1c39f7e44855e45e0bfd56 100644 (file)
@@ -39,5 +39,6 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND)     += xen-blkfront.o
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += xen-blkback/
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
 obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
+obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
 
 swim_mod-y     := swim.o swim_asm.o
diff --git a/drivers/block/mtip32xx/Kconfig b/drivers/block/mtip32xx/Kconfig
new file mode 100644 (file)
index 0000000..b5dd14e
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# mtip32xx device driver configuration
+#
+
+config BLK_DEV_PCIESSD_MTIP32XX
+       tristate "Block Device Driver for Micron PCIe SSDs"
+       depends on HOTPLUG_PCI_PCIE
+       help
+          This enables the block driver for Micron PCIe SSDs.
diff --git a/drivers/block/mtip32xx/Makefile b/drivers/block/mtip32xx/Makefile
new file mode 100644 (file)
index 0000000..4fbef8c
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for  Block device driver for Micron PCIe SSD
+#
+
+obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx.o
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
new file mode 100644 (file)
index 0000000..b74eab7
--- /dev/null
@@ -0,0 +1,3651 @@
+/*
+ * Driver for the Micron P320 SSD
+ *   Copyright (C) 2011 Micron Technology, Inc.
+ *
+ * Portions of this code were derived from works subjected to the
+ * following copyright:
+ *    Copyright (C) 2009 Integrated Device Technology, 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.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/ata.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/compat.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/kthread.h>
+#include <../drivers/ata/ahci.h>
+#include "mtip32xx.h"
+
+#define HW_CMD_SLOT_SZ         (MTIP_MAX_COMMAND_SLOTS * 32)
+#define HW_CMD_TBL_SZ          (AHCI_CMD_TBL_HDR_SZ + (MTIP_MAX_SG * 16))
+#define HW_CMD_TBL_AR_SZ       (HW_CMD_TBL_SZ * MTIP_MAX_COMMAND_SLOTS)
+#define HW_PORT_PRIV_DMA_SZ \
+               (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ)
+
+#define HOST_HSORG             0xFC
+#define HSORG_DISABLE_SLOTGRP_INTR (1<<24)
+#define HSORG_DISABLE_SLOTGRP_PXIS (1<<16)
+#define HSORG_HWREV            0xFF00
+#define HSORG_STYLE            0x8
+#define HSORG_SLOTGROUPS       0x7
+
+#define PORT_COMMAND_ISSUE     0x38
+#define PORT_SDBV              0x7C
+
+#define PORT_OFFSET            0x100
+#define PORT_MEM_SIZE          0x80
+
+#define PORT_IRQ_ERR \
+       (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_CONNECT | \
+        PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS | PORT_IRQ_BAD_PMP | \
+        PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_NONFATAL | \
+        PORT_IRQ_OVERFLOW)
+#define PORT_IRQ_LEGACY \
+       (PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+#define PORT_IRQ_HANDLED \
+       (PORT_IRQ_SDB_FIS | PORT_IRQ_LEGACY | \
+        PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR | \
+        PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)
+#define DEF_PORT_IRQ \
+       (PORT_IRQ_ERR | PORT_IRQ_LEGACY | PORT_IRQ_SDB_FIS)
+
+/* product numbers */
+#define MTIP_PRODUCT_UNKNOWN   0x00
+#define MTIP_PRODUCT_ASICFPGA  0x11
+
+/* Device instance number, incremented each time a device is probed. */
+static int instance;
+
+/*
+ * Global variable used to hold the major block device number
+ * allocated in mtip_init().
+ */
+static int mtip_major;
+
+static DEFINE_SPINLOCK(rssd_index_lock);
+static DEFINE_IDA(rssd_index_ida);
+
+static int mtip_block_initialize(struct driver_data *dd);
+
+#ifdef CONFIG_COMPAT
+struct mtip_compat_ide_task_request_s {
+       __u8            io_ports[8];
+       __u8            hob_ports[8];
+       ide_reg_valid_t out_flags;
+       ide_reg_valid_t in_flags;
+       int             data_phase;
+       int             req_cmd;
+       compat_ulong_t  out_size;
+       compat_ulong_t  in_size;
+};
+#endif
+
+/*
+ * This function check_for_surprise_removal is called
+ * while card is removed from the system and it will
+ * read the vendor id from the configration space
+ *
+ * @pdev Pointer to the pci_dev structure.
+ *
+ * return value
+ *      true if device removed, else false
+ */
+static bool mtip_check_surprise_removal(struct pci_dev *pdev)
+{
+       u16 vendor_id = 0;
+
+       /* Read the vendorID from the configuration space */
+       pci_read_config_word(pdev, 0x00, &vendor_id);
+       if (vendor_id == 0xFFFF)
+               return true; /* device removed */
+
+       return false; /* device present */
+}
+
+/*
+ * This function is called for clean the pending command in the
+ * command slot during the surprise removal of device and return
+ * error to the upper layer.
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_command_cleanup(struct driver_data *dd)
+{
+       int group = 0, commandslot = 0, commandindex = 0;
+       struct mtip_cmd *command;
+       struct mtip_port *port = dd->port;
+
+       for (group = 0; group < 4; group++) {
+               for (commandslot = 0; commandslot < 32; commandslot++) {
+                       if (!(port->allocated[group] & (1 << commandslot)))
+                               continue;
+
+                       commandindex = group << 5 | commandslot;
+                       command = &port->commands[commandindex];
+
+                       if (atomic_read(&command->active)
+                           && (command->async_callback)) {
+                               command->async_callback(command->async_data,
+                                       -ENODEV);
+                               command->async_callback = NULL;
+                               command->async_data = NULL;
+                       }
+
+                       dma_unmap_sg(&port->dd->pdev->dev,
+                               command->sg,
+                               command->scatter_ents,
+                               command->direction);
+               }
+       }
+
+       up(&port->cmd_slot);
+
+       atomic_set(&dd->drv_cleanup_done, true);
+}
+
+/*
+ * Obtain an empty command slot.
+ *
+ * This function needs to be reentrant since it could be called
+ * at the same time on multiple CPUs. The allocation of the
+ * command slot must be atomic.
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ *     >= 0    Index of command slot obtained.
+ *     -1      No command slots available.
+ */
+static int get_slot(struct mtip_port *port)
+{
+       int slot, i;
+       unsigned int num_command_slots = port->dd->slot_groups * 32;
+
+       /*
+        * Try 10 times, because there is a small race here.
+        *  that's ok, because it's still cheaper than a lock.
+        *
+        * Race: Since this section is not protected by lock, same bit
+        * could be chosen by different process contexts running in
+        * different processor. So instead of costly lock, we are going
+        * with loop.
+        */
+       for (i = 0; i < 10; i++) {
+               slot = find_next_zero_bit(port->allocated,
+                                        num_command_slots, 1);
+               if ((slot < num_command_slots) &&
+                   (!test_and_set_bit(slot, port->allocated)))
+                       return slot;
+       }
+       dev_warn(&port->dd->pdev->dev, "Failed to get a tag.\n");
+
+       if (mtip_check_surprise_removal(port->dd->pdev)) {
+               /* Device not present, clean outstanding commands */
+               mtip_command_cleanup(port->dd);
+       }
+       return -1;
+}
+
+/*
+ * Release a command slot.
+ *
+ * @port Pointer to the port data structure.
+ * @tag  Tag of command to release
+ *
+ * return value
+ *     None
+ */
+static inline void release_slot(struct mtip_port *port, int tag)
+{
+       smp_mb__before_clear_bit();
+       clear_bit(tag, port->allocated);
+       smp_mb__after_clear_bit();
+}
+
+/*
+ * Reset the HBA (without sleeping)
+ *
+ * Just like hba_reset, except does not call sleep, so can be
+ * run from interrupt/tasklet context.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0       The reset was successful.
+ *     -1      The HBA Reset bit did not clear.
+ */
+static int hba_reset_nosleep(struct driver_data *dd)
+{
+       unsigned long timeout;
+
+       /* Chip quirk: quiesce any chip function */
+       mdelay(10);
+
+       /* Set the reset bit */
+       writel(HOST_RESET, dd->mmio + HOST_CTL);
+
+       /* Flush */
+       readl(dd->mmio + HOST_CTL);
+
+       /*
+        * Wait 10ms then spin for up to 1 second
+        * waiting for reset acknowledgement
+        */
+       timeout = jiffies + msecs_to_jiffies(1000);
+       mdelay(10);
+       while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
+                && time_before(jiffies, timeout))
+               mdelay(1);
+
+       if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Issue a command to the hardware.
+ *
+ * Set the appropriate bit in the s_active and Command Issue hardware
+ * registers, causing hardware command processing to begin.
+ *
+ * @port Pointer to the port structure.
+ * @tag  The tag of the command to be issued.
+ *
+ * return value
+ *      None
+ */
+static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag)
+{
+       unsigned long flags = 0;
+
+       atomic_set(&port->commands[tag].active, 1);
+
+       spin_lock_irqsave(&port->cmd_issue_lock, flags);
+
+       writel((1 << MTIP_TAG_BIT(tag)),
+                       port->s_active[MTIP_TAG_INDEX(tag)]);
+       writel((1 << MTIP_TAG_BIT(tag)),
+                       port->cmd_issue[MTIP_TAG_INDEX(tag)]);
+
+       spin_unlock_irqrestore(&port->cmd_issue_lock, flags);
+}
+
+/*
+ * Enable/disable the reception of FIS
+ *
+ * @port   Pointer to the port data structure
+ * @enable 1 to enable, 0 to disable
+ *
+ * return value
+ *     Previous state: 1 enabled, 0 disabled
+ */
+static int mtip_enable_fis(struct mtip_port *port, int enable)
+{
+       u32 tmp;
+
+       /* enable FIS reception */
+       tmp = readl(port->mmio + PORT_CMD);
+       if (enable)
+               writel(tmp | PORT_CMD_FIS_RX, port->mmio + PORT_CMD);
+       else
+               writel(tmp & ~PORT_CMD_FIS_RX, port->mmio + PORT_CMD);
+
+       /* Flush */
+       readl(port->mmio + PORT_CMD);
+
+       return (((tmp & PORT_CMD_FIS_RX) == PORT_CMD_FIS_RX));
+}
+
+/*
+ * Enable/disable the DMA engine
+ *
+ * @port   Pointer to the port data structure
+ * @enable 1 to enable, 0 to disable
+ *
+ * return value
+ *     Previous state: 1 enabled, 0 disabled.
+ */
+static int mtip_enable_engine(struct mtip_port *port, int enable)
+{
+       u32 tmp;
+
+       /* enable FIS reception */
+       tmp = readl(port->mmio + PORT_CMD);
+       if (enable)
+               writel(tmp | PORT_CMD_START, port->mmio + PORT_CMD);
+       else
+               writel(tmp & ~PORT_CMD_START, port->mmio + PORT_CMD);
+
+       readl(port->mmio + PORT_CMD);
+       return (((tmp & PORT_CMD_START) == PORT_CMD_START));
+}
+
+/*
+ * Enables the port DMA engine and FIS reception.
+ *
+ * return value
+ *     None
+ */
+static inline void mtip_start_port(struct mtip_port *port)
+{
+       /* Enable FIS reception */
+       mtip_enable_fis(port, 1);
+
+       /* Enable the DMA engine */
+       mtip_enable_engine(port, 1);
+}
+
+/*
+ * Deinitialize a port by disabling port interrupts, the DMA engine,
+ * and FIS reception.
+ *
+ * @port Pointer to the port structure
+ *
+ * return value
+ *     None
+ */
+static inline void mtip_deinit_port(struct mtip_port *port)
+{
+       /* Disable interrupts on this port */
+       writel(0, port->mmio + PORT_IRQ_MASK);
+
+       /* Disable the DMA engine */
+       mtip_enable_engine(port, 0);
+
+       /* Disable FIS reception */
+       mtip_enable_fis(port, 0);
+}
+
+/*
+ * Initialize a port.
+ *
+ * This function deinitializes the port by calling mtip_deinit_port() and
+ * then initializes it by setting the command header and RX FIS addresses,
+ * clearing the SError register and any pending port interrupts before
+ * re-enabling the default set of port interrupts.
+ *
+ * @port Pointer to the port structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_init_port(struct mtip_port *port)
+{
+       int i;
+       mtip_deinit_port(port);
+
+       /* Program the command list base and FIS base addresses */
+       if (readl(port->dd->mmio + HOST_CAP) & HOST_CAP_64) {
+               writel((port->command_list_dma >> 16) >> 16,
+                        port->mmio + PORT_LST_ADDR_HI);
+               writel((port->rxfis_dma >> 16) >> 16,
+                        port->mmio + PORT_FIS_ADDR_HI);
+       }
+
+       writel(port->command_list_dma & 0xFFFFFFFF,
+                       port->mmio + PORT_LST_ADDR);
+       writel(port->rxfis_dma & 0xFFFFFFFF, port->mmio + PORT_FIS_ADDR);
+
+       /* Clear SError */
+       writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+
+       /* reset the completed registers.*/
+       for (i = 0; i < port->dd->slot_groups; i++)
+               writel(0xFFFFFFFF, port->completed[i]);
+
+       /* Clear any pending interrupts for this port */
+       writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT);
+
+       /* Enable port interrupts */
+       writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK);
+}
+
+/*
+ * Restart a port
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_restart_port(struct mtip_port *port)
+{
+       unsigned long timeout;
+
+       /* Disable the DMA engine */
+       mtip_enable_engine(port, 0);
+
+       /* Chip quirk: wait up to 500ms for PxCMD.CR == 0 */
+       timeout = jiffies + msecs_to_jiffies(500);
+       while ((readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON)
+                && time_before(jiffies, timeout))
+               ;
+
+       /*
+        * Chip quirk: escalate to hba reset if
+        * PxCMD.CR not clear after 500 ms
+        */
+       if (readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON) {
+               dev_warn(&port->dd->pdev->dev,
+                       "PxCMD.CR not clear, escalating reset\n");
+
+               if (hba_reset_nosleep(port->dd))
+                       dev_err(&port->dd->pdev->dev,
+                               "HBA reset escalation failed.\n");
+
+               /* 30 ms delay before com reset to quiesce chip */
+               mdelay(30);
+       }
+
+       dev_warn(&port->dd->pdev->dev, "Issuing COM reset\n");
+
+       /* Set PxSCTL.DET */
+       writel(readl(port->mmio + PORT_SCR_CTL) |
+                        1, port->mmio + PORT_SCR_CTL);
+       readl(port->mmio + PORT_SCR_CTL);
+
+       /* Wait 1 ms to quiesce chip function */
+       timeout = jiffies + msecs_to_jiffies(1);
+       while (time_before(jiffies, timeout))
+               ;
+
+       /* Clear PxSCTL.DET */
+       writel(readl(port->mmio + PORT_SCR_CTL) & ~1,
+                        port->mmio + PORT_SCR_CTL);
+       readl(port->mmio + PORT_SCR_CTL);
+
+       /* Wait 500 ms for bit 0 of PORT_SCR_STS to be set */
+       timeout = jiffies + msecs_to_jiffies(500);
+       while (((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
+                        && time_before(jiffies, timeout))
+               ;
+
+       if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
+               dev_warn(&port->dd->pdev->dev,
+                       "COM reset failed\n");
+
+       /* Clear SError, the PxSERR.DIAG.x should be set so clear it */
+       writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+
+       /* Enable the DMA engine */
+       mtip_enable_engine(port, 1);
+}
+
+/*
+ * Called periodically to see if any read/write commands are
+ * taking too long to complete.
+ *
+ * @data Pointer to the PORT data structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_timeout_function(unsigned long int data)
+{
+       struct mtip_port *port = (struct mtip_port *) data;
+       struct host_to_dev_fis *fis;
+       struct mtip_cmd *command;
+       int tag, cmdto_cnt = 0;
+       unsigned int bit, group;
+       unsigned int num_command_slots = port->dd->slot_groups * 32;
+
+       if (unlikely(!port))
+               return;
+
+       if (atomic_read(&port->dd->resumeflag) == true) {
+               mod_timer(&port->cmd_timer,
+                       jiffies + msecs_to_jiffies(30000));
+               return;
+       }
+
+       for (tag = 0; tag < num_command_slots; tag++) {
+               /*
+                * Skip internal command slot as it has
+                * its own timeout mechanism
+                */
+               if (tag == MTIP_TAG_INTERNAL)
+                       continue;
+
+               if (atomic_read(&port->commands[tag].active) &&
+                  (time_after(jiffies, port->commands[tag].comp_time))) {
+                       group = tag >> 5;
+                       bit = tag & 0x1F;
+
+                       command = &port->commands[tag];
+                       fis = (struct host_to_dev_fis *) command->command;
+
+                       dev_warn(&port->dd->pdev->dev,
+                               "Timeout for command tag %d\n", tag);
+
+                       cmdto_cnt++;
+                       if (cmdto_cnt == 1)
+                               set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+
+                       /*
+                        * Clear the completed bit. This should prevent
+                        *  any interrupt handlers from trying to retire
+                        *  the command.
+                        */
+                       writel(1 << bit, port->completed[group]);
+
+                       /* Call the async completion callback. */
+                       if (likely(command->async_callback))
+                               command->async_callback(command->async_data,
+                                                        -EIO);
+                       command->async_callback = NULL;
+                       command->comp_func = NULL;
+
+                       /* Unmap the DMA scatter list entries */
+                       dma_unmap_sg(&port->dd->pdev->dev,
+                                       command->sg,
+                                       command->scatter_ents,
+                                       command->direction);
+
+                       /*
+                        * Clear the allocated bit and active tag for the
+                        * command.
+                        */
+                       atomic_set(&port->commands[tag].active, 0);
+                       release_slot(port, tag);
+
+                       up(&port->cmd_slot);
+               }
+       }
+
+       if (cmdto_cnt) {
+               dev_warn(&port->dd->pdev->dev,
+                       "%d commands timed out: restarting port",
+                       cmdto_cnt);
+               mtip_restart_port(port);
+               clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+               wake_up_interruptible(&port->svc_wait);
+       }
+
+       /* Restart the timer */
+       mod_timer(&port->cmd_timer,
+               jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+}
+
+/*
+ * IO completion function.
+ *
+ * This completion function is called by the driver ISR when a
+ * command that was issued by the kernel completes. It first calls the
+ * asynchronous completion function which normally calls back into the block
+ * layer passing the asynchronous callback data, then unmaps the
+ * scatter list associated with the completed command, and finally
+ * clears the allocated bit associated with the completed command.
+ *
+ * @port   Pointer to the port data structure.
+ * @tag    Tag of the command.
+ * @data   Pointer to driver_data.
+ * @status Completion status.
+ *
+ * return value
+ *     None
+ */
+static void mtip_async_complete(struct mtip_port *port,
+                               int tag,
+                               void *data,
+                               int status)
+{
+       struct mtip_cmd *command;
+       struct driver_data *dd = data;
+       int cb_status = status ? -EIO : 0;
+
+       if (unlikely(!dd) || unlikely(!port))
+               return;
+
+       command = &port->commands[tag];
+
+       if (unlikely(status == PORT_IRQ_TF_ERR)) {
+               dev_warn(&port->dd->pdev->dev,
+                       "Command tag %d failed due to TFE\n", tag);
+       }
+
+       /* Upper layer callback */
+       if (likely(command->async_callback))
+               command->async_callback(command->async_data, cb_status);
+
+       command->async_callback = NULL;
+       command->comp_func = NULL;
+
+       /* Unmap the DMA scatter list entries */
+       dma_unmap_sg(&dd->pdev->dev,
+               command->sg,
+               command->scatter_ents,
+               command->direction);
+
+       /* Clear the allocated and active bits for the command */
+       atomic_set(&port->commands[tag].active, 0);
+       release_slot(port, tag);
+
+       up(&port->cmd_slot);
+}
+
+/*
+ * Internal command completion callback function.
+ *
+ * This function is normally called by the driver ISR when an internal
+ * command completed. This function signals the command completion by
+ * calling complete().
+ *
+ * @port   Pointer to the port data structure.
+ * @tag    Tag of the command that has completed.
+ * @data   Pointer to a completion structure.
+ * @status Completion status.
+ *
+ * return value
+ *     None
+ */
+static void mtip_completion(struct mtip_port *port,
+                           int tag,
+                           void *data,
+                           int status)
+{
+       struct mtip_cmd *command = &port->commands[tag];
+       struct completion *waiting = data;
+       if (unlikely(status == PORT_IRQ_TF_ERR))
+               dev_warn(&port->dd->pdev->dev,
+                       "Internal command %d completed with TFE\n", tag);
+
+       command->async_callback = NULL;
+       command->comp_func = NULL;
+
+       complete(waiting);
+}
+
+/*
+ * Helper function for tag logging
+ */
+static void print_tags(struct driver_data *dd,
+                       char *msg,
+                       unsigned long *tagbits)
+{
+       unsigned int tag, count = 0;
+
+       for (tag = 0; tag < (dd->slot_groups) * 32; tag++) {
+               if (test_bit(tag, tagbits))
+                       count++;
+       }
+       if (count)
+               dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count);
+}
+
+/*
+ * Handle an error.
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_handle_tfe(struct driver_data *dd)
+{
+       int group, tag, bit, reissue;
+       struct mtip_port *port;
+       struct mtip_cmd  *command;
+       u32 completed;
+       struct host_to_dev_fis *fis;
+       unsigned long tagaccum[SLOTBITS_IN_LONGS];
+
+       dev_warn(&dd->pdev->dev, "Taskfile error\n");
+
+       port = dd->port;
+
+       /* Stop the timer to prevent command timeouts. */
+       del_timer(&port->cmd_timer);
+
+       /* Set eh_active */
+       set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+
+       /* Loop through all the groups */
+       for (group = 0; group < dd->slot_groups; group++) {
+               completed = readl(port->completed[group]);
+
+               /* clear completed status register in the hardware.*/
+               writel(completed, port->completed[group]);
+
+               /* clear the tag accumulator */
+               memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
+               /* Process successfully completed commands */
+               for (bit = 0; bit < 32 && completed; bit++) {
+                       if (!(completed & (1<<bit)))
+                               continue;
+                       tag = (group << 5) + bit;
+
+                       /* Skip the internal command slot */
+                       if (tag == MTIP_TAG_INTERNAL)
+                               continue;
+
+                       command = &port->commands[tag];
+                       if (likely(command->comp_func)) {
+                               set_bit(tag, tagaccum);
+                               atomic_set(&port->commands[tag].active, 0);
+                               command->comp_func(port,
+                                        tag,
+                                        command->comp_data,
+                                        0);
+                       } else {
+                               dev_err(&port->dd->pdev->dev,
+                                       "Missing completion func for tag %d",
+                                       tag);
+                               if (mtip_check_surprise_removal(dd->pdev)) {
+                                       mtip_command_cleanup(dd);
+                                       /* don't proceed further */
+                                       return;
+                               }
+                       }
+               }
+       }
+       print_tags(dd, "TFE tags completed:", tagaccum);
+
+       /* Restart the port */
+       mdelay(20);
+       mtip_restart_port(port);
+
+       /* clear the tag accumulator */
+       memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
+       /* Loop through all the groups */
+       for (group = 0; group < dd->slot_groups; group++) {
+               for (bit = 0; bit < 32; bit++) {
+                       reissue = 1;
+                       tag = (group << 5) + bit;
+
+                       /* If the active bit is set re-issue the command */
+                       if (atomic_read(&port->commands[tag].active) == 0)
+                               continue;
+
+                       fis = (struct host_to_dev_fis *)
+                               port->commands[tag].command;
+
+                       /* Should re-issue? */
+                       if (tag == MTIP_TAG_INTERNAL ||
+                           fis->command == ATA_CMD_SET_FEATURES)
+                               reissue = 0;
+
+                       /*
+                        * First check if this command has
+                        *  exceeded its retries.
+                        */
+                       if (reissue &&
+                           (port->commands[tag].retries-- > 0)) {
+
+                               set_bit(tag, tagaccum);
+
+                               /* Update the timeout value. */
+                               port->commands[tag].comp_time =
+                                       jiffies + msecs_to_jiffies(
+                                       MTIP_NCQ_COMMAND_TIMEOUT_MS);
+                               /* Re-issue the command. */
+                               mtip_issue_ncq_command(port, tag);
+
+                               continue;
+                       }
+
+                       /* Retire a command that will not be reissued */
+                       dev_warn(&port->dd->pdev->dev,
+                               "retiring tag %d\n", tag);
+                       atomic_set(&port->commands[tag].active, 0);
+
+                       if (port->commands[tag].comp_func)
+                               port->commands[tag].comp_func(
+                                       port,
+                                       tag,
+                                       port->commands[tag].comp_data,
+                                       PORT_IRQ_TF_ERR);
+                       else
+                               dev_warn(&port->dd->pdev->dev,
+                                       "Bad completion for tag %d\n",
+                                       tag);
+               }
+       }
+       print_tags(dd, "TFE tags reissued:", tagaccum);
+
+       /* clear eh_active */
+       clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+       wake_up_interruptible(&port->svc_wait);
+
+       mod_timer(&port->cmd_timer,
+                jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+}
+
+/*
+ * Handle a set device bits interrupt
+ */
+static inline void mtip_process_sdbf(struct driver_data *dd)
+{
+       struct mtip_port  *port = dd->port;
+       int group, tag, bit;
+       u32 completed;
+       struct mtip_cmd *command;
+
+       /* walk all bits in all slot groups */
+       for (group = 0; group < dd->slot_groups; group++) {
+               completed = readl(port->completed[group]);
+
+               /* clear completed status register in the hardware.*/
+               writel(completed, port->completed[group]);
+
+               /* Process completed commands. */
+               for (bit = 0;
+                    (bit < 32) && completed;
+                    bit++, completed >>= 1) {
+                       if (completed & 0x01) {
+                               tag = (group << 5) | bit;
+
+                               /* skip internal command slot. */
+                               if (unlikely(tag == MTIP_TAG_INTERNAL))
+                                       continue;
+
+                               command = &port->commands[tag];
+                               /* make internal callback */
+                               if (likely(command->comp_func)) {
+                                       command->comp_func(
+                                               port,
+                                               tag,
+                                               command->comp_data,
+                                               0);
+                               } else {
+                                       dev_warn(&dd->pdev->dev,
+                                               "Null completion "
+                                               "for tag %d",
+                                               tag);
+
+                                       if (mtip_check_surprise_removal(
+                                               dd->pdev)) {
+                                               mtip_command_cleanup(dd);
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+/*
+ * Process legacy pio and d2h interrupts
+ */
+static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat)
+{
+       struct mtip_port *port = dd->port;
+       struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL];
+
+       if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+           (cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+               & (1 << MTIP_TAG_INTERNAL))) {
+               if (cmd->comp_func) {
+                       cmd->comp_func(port,
+                               MTIP_TAG_INTERNAL,
+                               cmd->comp_data,
+                               0);
+                       return;
+               }
+       }
+
+       dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat);
+
+       return;
+}
+
+/*
+ * Demux and handle errors
+ */
+static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat)
+{
+       if (likely(port_stat & (PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR)))
+               mtip_handle_tfe(dd);
+
+       if (unlikely(port_stat & PORT_IRQ_CONNECT)) {
+               dev_warn(&dd->pdev->dev,
+                       "Clearing PxSERR.DIAG.x\n");
+               writel((1 << 26), dd->port->mmio + PORT_SCR_ERR);
+       }
+
+       if (unlikely(port_stat & PORT_IRQ_PHYRDY)) {
+               dev_warn(&dd->pdev->dev,
+                       "Clearing PxSERR.DIAG.n\n");
+               writel((1 << 16), dd->port->mmio + PORT_SCR_ERR);
+       }
+
+       if (unlikely(port_stat & ~PORT_IRQ_HANDLED)) {
+               dev_warn(&dd->pdev->dev,
+                       "Port stat errors %x unhandled\n",
+                       (port_stat & ~PORT_IRQ_HANDLED));
+       }
+}
+
+static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
+{
+       struct driver_data *dd = (struct driver_data *) data;
+       struct mtip_port *port = dd->port;
+       u32 hba_stat, port_stat;
+       int rv = IRQ_NONE;
+
+       hba_stat = readl(dd->mmio + HOST_IRQ_STAT);
+       if (hba_stat) {
+               rv = IRQ_HANDLED;
+
+               /* Acknowledge the interrupt status on the port.*/
+               port_stat = readl(port->mmio + PORT_IRQ_STAT);
+               writel(port_stat, port->mmio + PORT_IRQ_STAT);
+
+               /* Demux port status */
+               if (likely(port_stat & PORT_IRQ_SDB_FIS))
+                       mtip_process_sdbf(dd);
+
+               if (unlikely(port_stat & PORT_IRQ_ERR)) {
+                       if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
+                               mtip_command_cleanup(dd);
+                               /* don't proceed further */
+                               return IRQ_HANDLED;
+                       }
+
+                       mtip_process_errors(dd, port_stat & PORT_IRQ_ERR);
+               }
+
+               if (unlikely(port_stat & PORT_IRQ_LEGACY))
+                       mtip_process_legacy(dd, port_stat & PORT_IRQ_LEGACY);
+       }
+
+       /* acknowledge interrupt */
+       writel(hba_stat, dd->mmio + HOST_IRQ_STAT);
+
+       return rv;
+}
+
+/*
+ * Wrapper for mtip_handle_irq
+ * (ignores return code)
+ */
+static void mtip_tasklet(unsigned long data)
+{
+       mtip_handle_irq((struct driver_data *) data);
+}
+
+/*
+ * HBA interrupt subroutine.
+ *
+ * @irq                IRQ number.
+ * @instance   Pointer to the driver data structure.
+ *
+ * return value
+ *     IRQ_HANDLED     A HBA interrupt was pending and handled.
+ *     IRQ_NONE        This interrupt was not for the HBA.
+ */
+static irqreturn_t mtip_irq_handler(int irq, void *instance)
+{
+       struct driver_data *dd = instance;
+       tasklet_schedule(&dd->tasklet);
+       return IRQ_HANDLED;
+}
+
+static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag)
+{
+       atomic_set(&port->commands[tag].active, 1);
+       writel(1 << MTIP_TAG_BIT(tag),
+               port->cmd_issue[MTIP_TAG_INDEX(tag)]);
+}
+
+/*
+ * Wait for port to quiesce
+ *
+ * @port    Pointer to port data structure
+ * @timeout Max duration to wait (ms)
+ *
+ * return value
+ *     0       Success
+ *     -EBUSY  Commands still active
+ */
+static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
+{
+       unsigned long to;
+       unsigned int n;
+       unsigned int active = 1;
+
+       to = jiffies + msecs_to_jiffies(timeout);
+       do {
+               if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) &&
+                       test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+                       msleep(20);
+                       continue; /* svc thd is actively issuing commands */
+               }
+               /*
+                * Ignore s_active bit 0 of array element 0.
+                * This bit will always be set
+                */
+               active = readl(port->s_active[0]) & 0xFFFFFFFE;
+               for (n = 1; n < port->dd->slot_groups; n++)
+                       active |= readl(port->s_active[n]);
+
+               if (!active)
+                       break;
+
+               msleep(20);
+       } while (time_before(jiffies, to));
+
+       return active ? -EBUSY : 0;
+}
+
+/*
+ * Execute an internal command and wait for the completion.
+ *
+ * @port    Pointer to the port data structure.
+ * @fis     Pointer to the FIS that describes the command.
+ * @fis_len  Length in WORDS of the FIS.
+ * @buffer  DMA accessible for command data.
+ * @buf_len  Length, in bytes, of the data buffer.
+ * @opts    Command header options, excluding the FIS length
+ *             and the number of PRD entries.
+ * @timeout Time in ms to wait for the command to complete.
+ *
+ * return value
+ *     0        Command completed successfully.
+ *     -EFAULT  The buffer address is not correctly aligned.
+ *     -EBUSY   Internal command or other IO in progress.
+ *     -EAGAIN  Time out waiting for command to complete.
+ */
+static int mtip_exec_internal_command(struct mtip_port *port,
+                                       void *fis,
+                                       int fis_len,
+                                       dma_addr_t buffer,
+                                       int buf_len,
+                                       u32 opts,
+                                       gfp_t atomic,
+                                       unsigned long timeout)
+{
+       struct mtip_cmd_sg *command_sg;
+       DECLARE_COMPLETION_ONSTACK(wait);
+       int rv = 0;
+       struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
+
+       /* Make sure the buffer is 8 byte aligned. This is asic specific. */
+       if (buffer & 0x00000007) {
+               dev_err(&port->dd->pdev->dev,
+                       "SG buffer is not 8 byte aligned\n");
+               return -EFAULT;
+       }
+
+       /* Only one internal command should be running at a time */
+       if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) {
+               dev_warn(&port->dd->pdev->dev,
+                       "Internal command already active\n");
+               return -EBUSY;
+       }
+       set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+
+       if (atomic == GFP_KERNEL) {
+               /* wait for io to complete if non atomic */
+               if (mtip_quiesce_io(port, 5000) < 0) {
+                       dev_warn(&port->dd->pdev->dev,
+                               "Failed to quiesce IO\n");
+                       release_slot(port, MTIP_TAG_INTERNAL);
+                       clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+                       wake_up_interruptible(&port->svc_wait);
+                       return -EBUSY;
+               }
+
+               /* Set the completion function and data for the command. */
+               int_cmd->comp_data = &wait;
+               int_cmd->comp_func = mtip_completion;
+
+       } else {
+               /* Clear completion - we're going to poll */
+               int_cmd->comp_data = NULL;
+               int_cmd->comp_func = NULL;
+       }
+
+       /* Copy the command to the command table */
+       memcpy(int_cmd->command, fis, fis_len*4);
+
+       /* Populate the SG list */
+       int_cmd->command_header->opts =
+                __force_bit2int cpu_to_le32(opts | fis_len);
+       if (buf_len) {
+               command_sg = int_cmd->command + AHCI_CMD_TBL_HDR_SZ;
+
+               command_sg->info =
+                       __force_bit2int cpu_to_le32((buf_len-1) & 0x3FFFFF);
+               command_sg->dba =
+                       __force_bit2int cpu_to_le32(buffer & 0xFFFFFFFF);
+               command_sg->dba_upper =
+                       __force_bit2int cpu_to_le32((buffer >> 16) >> 16);
+
+               int_cmd->command_header->opts |=
+                       __force_bit2int cpu_to_le32((1 << 16));
+       }
+
+       /* Populate the command header */
+       int_cmd->command_header->byte_count = 0;
+
+       /* Issue the command to the hardware */
+       mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
+
+       /* Poll if atomic, wait_for_completion otherwise */
+       if (atomic == GFP_KERNEL) {
+               /* Wait for the command to complete or timeout. */
+               if (wait_for_completion_timeout(
+                               &wait,
+                               msecs_to_jiffies(timeout)) == 0) {
+                       dev_err(&port->dd->pdev->dev,
+                               "Internal command did not complete [%d] "
+                               "within timeout of  %lu ms\n",
+                               atomic, timeout);
+                       rv = -EAGAIN;
+               }
+
+               if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+                       & (1 << MTIP_TAG_INTERNAL)) {
+                       dev_warn(&port->dd->pdev->dev,
+                               "Retiring internal command but CI is 1.\n");
+               }
+
+       } else {
+               /* Spin for <timeout> checking if command still outstanding */
+               timeout = jiffies + msecs_to_jiffies(timeout);
+
+               while ((readl(
+                       port->cmd_issue[MTIP_TAG_INTERNAL])
+                       & (1 << MTIP_TAG_INTERNAL))
+                       && time_before(jiffies, timeout))
+                       ;
+
+               if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+                       & (1 << MTIP_TAG_INTERNAL)) {
+                       dev_err(&port->dd->pdev->dev,
+                               "Internal command did not complete [%d]\n",
+                               atomic);
+                       rv = -EAGAIN;
+               }
+       }
+
+       /* Clear the allocated and active bits for the internal command. */
+       atomic_set(&int_cmd->active, 0);
+       release_slot(port, MTIP_TAG_INTERNAL);
+       clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+       wake_up_interruptible(&port->svc_wait);
+
+       return rv;
+}
+
+/*
+ * Byte-swap ATA ID strings.
+ *
+ * ATA identify data contains strings in byte-swapped 16-bit words.
+ * They must be swapped (on all architectures) to be usable as C strings.
+ * This function swaps bytes in-place.
+ *
+ * @buf The buffer location of the string
+ * @len The number of bytes to swap
+ *
+ * return value
+ *     None
+ */
+static inline void ata_swap_string(u16 *buf, unsigned int len)
+{
+       int i;
+       for (i = 0; i < (len/2); i++)
+               be16_to_cpus(&buf[i]);
+}
+
+/*
+ * Request the device identity information.
+ *
+ * If a user space buffer is not specified, i.e. is NULL, the
+ * identify information is still read from the drive and placed
+ * into the identify data buffer (@e port->identify) in the
+ * port data structure.
+ * When the identify buffer contains valid identify information @e
+ * port->identify_valid is non-zero.
+ *
+ * @port        Pointer to the port structure.
+ * @user_buffer  A user space buffer where the identify data should be
+ *                    copied.
+ *
+ * return value
+ *     0       Command completed successfully.
+ *     -EFAULT An error occurred while coping data to the user buffer.
+ *     -1      Command failed.
+ */
+static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer)
+{
+       int rv = 0;
+       struct host_to_dev_fis fis;
+
+       /* Build the FIS. */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = ATA_CMD_ID_ATA;
+
+       /* Set the identify information as invalid. */
+       port->identify_valid = 0;
+
+       /* Clear the identify information. */
+       memset(port->identify, 0, sizeof(u16) * ATA_ID_WORDS);
+
+       /* Execute the command. */
+       if (mtip_exec_internal_command(port,
+                               &fis,
+                               5,
+                               port->identify_dma,
+                               sizeof(u16) * ATA_ID_WORDS,
+                               0,
+                               GFP_KERNEL,
+                               MTIP_INTERNAL_COMMAND_TIMEOUT_MS)
+                               < 0) {
+               rv = -1;
+               goto out;
+       }
+
+       /*
+        * Perform any necessary byte-swapping.  Yes, the kernel does in fact
+        * perform field-sensitive swapping on the string fields.
+        * See the kernel use of ata_id_string() for proof of this.
+        */
+#ifdef __LITTLE_ENDIAN
+       ata_swap_string(port->identify + 27, 40);  /* model string*/
+       ata_swap_string(port->identify + 23, 8);   /* firmware string*/
+       ata_swap_string(port->identify + 10, 20);  /* serial# string*/
+#else
+       {
+               int i;
+               for (i = 0; i < ATA_ID_WORDS; i++)
+                       port->identify[i] = le16_to_cpu(port->identify[i]);
+       }
+#endif
+
+       /* Set the identify buffer as valid. */
+       port->identify_valid = 1;
+
+       if (user_buffer) {
+               if (copy_to_user(
+                       user_buffer,
+                       port->identify,
+                       ATA_ID_WORDS * sizeof(u16))) {
+                       rv = -EFAULT;
+                       goto out;
+               }
+       }
+
+out:
+       return rv;
+}
+
+/*
+ * Issue a standby immediate command to the device.
+ *
+ * @port Pointer to the port structure.
+ *
+ * return value
+ *     0       Command was executed successfully.
+ *     -1      An error occurred while executing the command.
+ */
+static int mtip_standby_immediate(struct mtip_port *port)
+{
+       int rv;
+       struct host_to_dev_fis  fis;
+
+       /* Build the FIS. */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = ATA_CMD_STANDBYNOW1;
+
+       /* Execute the command.  Use a 15-second timeout for large drives. */
+       rv = mtip_exec_internal_command(port,
+                                       &fis,
+                                       5,
+                                       0,
+                                       0,
+                                       0,
+                                       GFP_KERNEL,
+                                       15000);
+
+       return rv;
+}
+
+/*
+ * Get the drive capacity.
+ *
+ * @dd      Pointer to the device data structure.
+ * @sectors Pointer to the variable that will receive the sector count.
+ *
+ * return value
+ *     1 Capacity was returned successfully.
+ *     0 The identify information is invalid.
+ */
+static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors)
+{
+       struct mtip_port *port = dd->port;
+       u64 total, raw0, raw1, raw2, raw3;
+       raw0 = port->identify[100];
+       raw1 = port->identify[101];
+       raw2 = port->identify[102];
+       raw3 = port->identify[103];
+       total = raw0 | raw1<<16 | raw2<<32 | raw3<<48;
+       *sectors = total;
+       return (bool) !!port->identify_valid;
+}
+
+/*
+ * Reset the HBA.
+ *
+ * Resets the HBA by setting the HBA Reset bit in the Global
+ * HBA Control register. After setting the HBA Reset bit the
+ * function waits for 1 second before reading the HBA Reset
+ * bit to make sure it has cleared. If HBA Reset is not clear
+ * an error is returned. Cannot be used in non-blockable
+ * context.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0  The reset was successful.
+ *     -1 The HBA Reset bit did not clear.
+ */
+static int mtip_hba_reset(struct driver_data *dd)
+{
+       mtip_deinit_port(dd->port);
+
+       /* Set the reset bit */
+       writel(HOST_RESET, dd->mmio + HOST_CTL);
+
+       /* Flush */
+       readl(dd->mmio + HOST_CTL);
+
+       /* Wait for reset to clear */
+       ssleep(1);
+
+       /* Check the bit has cleared */
+       if (readl(dd->mmio + HOST_CTL) & HOST_RESET) {
+               dev_err(&dd->pdev->dev,
+                       "Reset bit did not clear.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Display the identify command data.
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_dump_identify(struct mtip_port *port)
+{
+       sector_t sectors;
+       unsigned short revid;
+       char cbuf[42];
+
+       if (!port->identify_valid)
+               return;
+
+       strlcpy(cbuf, (char *)(port->identify+10), 21);
+       dev_info(&port->dd->pdev->dev,
+               "Serial No.: %s\n", cbuf);
+
+       strlcpy(cbuf, (char *)(port->identify+23), 9);
+       dev_info(&port->dd->pdev->dev,
+               "Firmware Ver.: %s\n", cbuf);
+
+       strlcpy(cbuf, (char *)(port->identify+27), 41);
+       dev_info(&port->dd->pdev->dev, "Model: %s\n", cbuf);
+
+       if (mtip_hw_get_capacity(port->dd, &sectors))
+               dev_info(&port->dd->pdev->dev,
+                       "Capacity: %llu sectors (%llu MB)\n",
+                        (u64)sectors,
+                        ((u64)sectors) * ATA_SECT_SIZE >> 20);
+
+       pci_read_config_word(port->dd->pdev, PCI_REVISION_ID, &revid);
+       switch (revid & 0xFF) {
+       case 0x1:
+               strlcpy(cbuf, "A0", 3);
+               break;
+       case 0x3:
+               strlcpy(cbuf, "A2", 3);
+               break;
+       default:
+               strlcpy(cbuf, "?", 2);
+               break;
+       }
+       dev_info(&port->dd->pdev->dev,
+               "Card Type: %s\n", cbuf);
+}
+
+/*
+ * Map the commands scatter list into the command table.
+ *
+ * @command Pointer to the command.
+ * @nents Number of scatter list entries.
+ *
+ * return value
+ *     None
+ */
+static inline void fill_command_sg(struct driver_data *dd,
+                               struct mtip_cmd *command,
+                               int nents)
+{
+       int n;
+       unsigned int dma_len;
+       struct mtip_cmd_sg *command_sg;
+       struct scatterlist *sg = command->sg;
+
+       command_sg = command->command + AHCI_CMD_TBL_HDR_SZ;
+
+       for (n = 0; n < nents; n++) {
+               dma_len = sg_dma_len(sg);
+               if (dma_len > 0x400000)
+                       dev_err(&dd->pdev->dev,
+                               "DMA segment length truncated\n");
+               command_sg->info = __force_bit2int
+                       cpu_to_le32((dma_len-1) & 0x3FFFFF);
+               command_sg->dba = __force_bit2int
+                       cpu_to_le32(sg_dma_address(sg));
+               command_sg->dba_upper = __force_bit2int
+                       cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
+               command_sg++;
+               sg++;
+       }
+}
+
+/*
+ * @brief Execute a drive command.
+ *
+ * return value 0 The command completed successfully.
+ * return value -1 An error occurred while executing the command.
+ */
+static int exec_drive_task(struct mtip_port *port, u8 *command)
+{
+       struct host_to_dev_fis  fis;
+       struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG);
+
+       /* Build the FIS. */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = command[0];
+       fis.features    = command[1];
+       fis.sect_count  = command[2];
+       fis.sector      = command[3];
+       fis.cyl_low     = command[4];
+       fis.cyl_hi      = command[5];
+       fis.device      = command[6] & ~0x10; /* Clear the dev bit*/
+
+
+       dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, "
+               "nsect %x, sect %x, lcyl %x, "
+               "hcyl %x, sel %x\n",
+               __func__,
+               command[0],
+               command[1],
+               command[2],
+               command[3],
+               command[4],
+               command[5],
+               command[6]);
+
+       /* Execute the command. */
+       if (mtip_exec_internal_command(port,
+                                &fis,
+                                5,
+                                0,
+                                0,
+                                0,
+                                GFP_KERNEL,
+                                MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) {
+               return -1;
+       }
+
+       command[0] = reply->command; /* Status*/
+       command[1] = reply->features; /* Error*/
+       command[4] = reply->cyl_low;
+       command[5] = reply->cyl_hi;
+
+       dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, "
+               "err %x , cyl_lo %x cyl_hi %x\n",
+               __func__,
+               command[0],
+               command[1],
+               command[4],
+               command[5]);
+
+       return 0;
+}
+
+/*
+ * @brief Execute a drive command.
+ *
+ * @param port Pointer to the port data structure.
+ * @param command Pointer to the user specified command parameters.
+ * @param user_buffer Pointer to the user space buffer where read sector
+ *                   data should be copied.
+ *
+ * return value 0 The command completed successfully.
+ * return value -EFAULT An error occurred while copying the completion
+ *                 data to the user space buffer.
+ * return value -1 An error occurred while executing the command.
+ */
+static int exec_drive_command(struct mtip_port *port, u8 *command,
+                               void __user *user_buffer)
+{
+       struct host_to_dev_fis  fis;
+       struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG);
+
+       /* Build the FIS. */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type                = 0x27;
+       fis.opts                = 1 << 7;
+       fis.command             = command[0];
+       fis.features    = command[2];
+       fis.sect_count  = command[3];
+       if (fis.command == ATA_CMD_SMART) {
+               fis.sector      = command[1];
+               fis.cyl_low     = 0x4F;
+               fis.cyl_hi      = 0xC2;
+       }
+
+       dbg_printk(MTIP_DRV_NAME
+               "%s: User Command: cmd %x, sect %x, "
+               "feat %x, sectcnt %x\n",
+               __func__,
+               command[0],
+               command[1],
+               command[2],
+               command[3]);
+
+       memset(port->sector_buffer, 0x00, ATA_SECT_SIZE);
+
+       /* Execute the command. */
+       if (mtip_exec_internal_command(port,
+                               &fis,
+                                5,
+                                port->sector_buffer_dma,
+                                (command[3] != 0) ? ATA_SECT_SIZE : 0,
+                                0,
+                                GFP_KERNEL,
+                                MTIP_IOCTL_COMMAND_TIMEOUT_MS)
+                                < 0) {
+               return -1;
+       }
+
+       /* Collect the completion status. */
+       command[0] = reply->command; /* Status*/
+       command[1] = reply->features; /* Error*/
+       command[2] = command[3];
+
+       dbg_printk(MTIP_DRV_NAME
+               "%s: Completion Status: stat %x, "
+               "err %x, cmd %x\n",
+               __func__,
+               command[0],
+               command[1],
+               command[2]);
+
+       if (user_buffer && command[3]) {
+               if (copy_to_user(user_buffer,
+                                port->sector_buffer,
+                                ATA_SECT_SIZE * command[3])) {
+                       return -EFAULT;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ *  Indicates whether a command has a single sector payload.
+ *
+ *  @command passed to the device to perform the certain event.
+ *  @features passed to the device to perform the certain event.
+ *
+ *  return value
+ *     1       command is one that always has a single sector payload,
+ *             regardless of the value in the Sector Count field.
+ *      0       otherwise
+ *
+ */
+static unsigned int implicit_sector(unsigned char command,
+                                   unsigned char features)
+{
+       unsigned int rv = 0;
+
+       /* list of commands that have an implicit sector count of 1 */
+       switch (command) {
+       case ATA_CMD_SEC_SET_PASS:
+       case ATA_CMD_SEC_UNLOCK:
+       case ATA_CMD_SEC_ERASE_PREP:
+       case ATA_CMD_SEC_ERASE_UNIT:
+       case ATA_CMD_SEC_FREEZE_LOCK:
+       case ATA_CMD_SEC_DISABLE_PASS:
+       case ATA_CMD_PMP_READ:
+       case ATA_CMD_PMP_WRITE:
+               rv = 1;
+               break;
+       case ATA_CMD_SET_MAX:
+               if (features == ATA_SET_MAX_UNLOCK)
+                       rv = 1;
+               break;
+       case ATA_CMD_SMART:
+               if ((features == ATA_SMART_READ_VALUES) ||
+                               (features == ATA_SMART_READ_THRESHOLDS))
+                       rv = 1;
+               break;
+       case ATA_CMD_CONF_OVERLAY:
+               if ((features == ATA_DCO_IDENTIFY) ||
+                               (features == ATA_DCO_SET))
+                       rv = 1;
+               break;
+       }
+       return rv;
+}
+
+/*
+ * Executes a taskfile
+ * See ide_taskfile_ioctl() for derivation
+ */
+static int exec_drive_taskfile(struct driver_data *dd,
+                              void __user *buf,
+                              ide_task_request_t *req_task,
+                              int outtotal)
+{
+       struct host_to_dev_fis  fis;
+       struct host_to_dev_fis *reply;
+       u8 *outbuf = NULL;
+       u8 *inbuf = NULL;
+       dma_addr_t outbuf_dma = 0;
+       dma_addr_t inbuf_dma = 0;
+       dma_addr_t dma_buffer = 0;
+       int err = 0;
+       unsigned int taskin = 0;
+       unsigned int taskout = 0;
+       u8 nsect = 0;
+       unsigned int timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
+       unsigned int force_single_sector;
+       unsigned int transfer_size;
+       unsigned long task_file_data;
+       int intotal = outtotal + req_task->out_size;
+
+       taskout = req_task->out_size;
+       taskin = req_task->in_size;
+       /* 130560 = 512 * 0xFF*/
+       if (taskin > 130560 || taskout > 130560) {
+               err = -EINVAL;
+               goto abort;
+       }
+
+       if (taskout) {
+               outbuf = kzalloc(taskout, GFP_KERNEL);
+               if (outbuf == NULL) {
+                       err = -ENOMEM;
+                       goto abort;
+               }
+               if (copy_from_user(outbuf, buf + outtotal, taskout)) {
+                       err = -EFAULT;
+                       goto abort;
+               }
+               outbuf_dma = pci_map_single(dd->pdev,
+                                        outbuf,
+                                        taskout,
+                                        DMA_TO_DEVICE);
+               if (outbuf_dma == 0) {
+                       err = -ENOMEM;
+                       goto abort;
+               }
+               dma_buffer = outbuf_dma;
+       }
+
+       if (taskin) {
+               inbuf = kzalloc(taskin, GFP_KERNEL);
+               if (inbuf == NULL) {
+                       err = -ENOMEM;
+                       goto abort;
+               }
+
+               if (copy_from_user(inbuf, buf + intotal, taskin)) {
+                       err = -EFAULT;
+                       goto abort;
+               }
+               inbuf_dma = pci_map_single(dd->pdev,
+                                        inbuf,
+                                        taskin, DMA_FROM_DEVICE);
+               if (inbuf_dma == 0) {
+                       err = -ENOMEM;
+                       goto abort;
+               }
+               dma_buffer = inbuf_dma;
+       }
+
+       /* only supports PIO and non-data commands from this ioctl. */
+       switch (req_task->data_phase) {
+       case TASKFILE_OUT:
+               nsect = taskout / ATA_SECT_SIZE;
+               reply = (dd->port->rxfis + RX_FIS_PIO_SETUP);
+               break;
+       case TASKFILE_IN:
+               reply = (dd->port->rxfis + RX_FIS_PIO_SETUP);
+               break;
+       case TASKFILE_NO_DATA:
+               reply = (dd->port->rxfis + RX_FIS_D2H_REG);
+               break;
+       default:
+               err = -EINVAL;
+               goto abort;
+       }
+
+       /* Build the FIS. */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = req_task->io_ports[7];
+       fis.features    = req_task->io_ports[1];
+       fis.sect_count  = req_task->io_ports[2];
+       fis.lba_low     = req_task->io_ports[3];
+       fis.lba_mid     = req_task->io_ports[4];
+       fis.lba_hi      = req_task->io_ports[5];
+        /* Clear the dev bit*/
+       fis.device      = req_task->io_ports[6] & ~0x10;
+
+       if ((req_task->in_flags.all == 0) && (req_task->out_flags.all & 1)) {
+               req_task->in_flags.all  =
+                       IDE_TASKFILE_STD_IN_FLAGS |
+                       (IDE_HOB_STD_IN_FLAGS << 8);
+               fis.lba_low_ex          = req_task->hob_ports[3];
+               fis.lba_mid_ex          = req_task->hob_ports[4];
+               fis.lba_hi_ex           = req_task->hob_ports[5];
+               fis.features_ex         = req_task->hob_ports[1];
+               fis.sect_cnt_ex         = req_task->hob_ports[2];
+
+       } else {
+               req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
+       }
+
+       force_single_sector = implicit_sector(fis.command, fis.features);
+
+       if ((taskin || taskout) && (!fis.sect_count)) {
+               if (nsect)
+                       fis.sect_count = nsect;
+               else {
+                       if (!force_single_sector) {
+                               dev_warn(&dd->pdev->dev,
+                                       "data movement but "
+                                       "sect_count is 0\n");
+                                       err = -EINVAL;
+                                       goto abort;
+                       }
+               }
+       }
+
+       dbg_printk(MTIP_DRV_NAME
+               "taskfile: cmd %x, feat %x, nsect %x,"
+               " sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x,"
+               " head/dev %x\n",
+               fis.command,
+               fis.features,
+               fis.sect_count,
+               fis.lba_low,
+               fis.lba_mid,
+               fis.lba_hi,
+               fis.device);
+
+       switch (fis.command) {
+       case ATA_CMD_DOWNLOAD_MICRO:
+               /* Change timeout for Download Microcode to 60 seconds.*/
+               timeout = 60000;
+               break;
+       case ATA_CMD_SEC_ERASE_UNIT:
+               /* Change timeout for Security Erase Unit to 4 minutes.*/
+               timeout = 240000;
+               break;
+       case ATA_CMD_STANDBYNOW1:
+               /* Change timeout for standby immediate to 10 seconds.*/
+               timeout = 10000;
+               break;
+       case 0xF7:
+       case 0xFA:
+               /* Change timeout for vendor unique command to 10 secs */
+               timeout = 10000;
+               break;
+       case ATA_CMD_SMART:
+               /* Change timeout for vendor unique command to 10 secs */
+               timeout = 10000;
+               break;
+       default:
+               timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
+               break;
+       }
+
+       /* Determine the correct transfer size.*/
+       if (force_single_sector)
+               transfer_size = ATA_SECT_SIZE;
+       else
+               transfer_size = ATA_SECT_SIZE * fis.sect_count;
+
+       /* Execute the command.*/
+       if (mtip_exec_internal_command(dd->port,
+                                &fis,
+                                5,
+                                dma_buffer,
+                                transfer_size,
+                                0,
+                                GFP_KERNEL,
+                                timeout) < 0) {
+               err = -EIO;
+               goto abort;
+       }
+
+       task_file_data = readl(dd->port->mmio+PORT_TFDATA);
+
+       if ((req_task->data_phase == TASKFILE_IN) && !(task_file_data & 1)) {
+               reply = dd->port->rxfis + RX_FIS_PIO_SETUP;
+               req_task->io_ports[7] = reply->control;
+       } else {
+               reply = dd->port->rxfis + RX_FIS_D2H_REG;
+               req_task->io_ports[7] = reply->command;
+       }
+
+       /* reclaim the DMA buffers.*/
+       if (inbuf_dma)
+               pci_unmap_single(dd->pdev, inbuf_dma,
+                       taskin, DMA_FROM_DEVICE);
+       if (outbuf_dma)
+               pci_unmap_single(dd->pdev, outbuf_dma,
+                       taskout, DMA_TO_DEVICE);
+       inbuf_dma  = 0;
+       outbuf_dma = 0;
+
+       /* return the ATA registers to the caller.*/
+       req_task->io_ports[1] = reply->features;
+       req_task->io_ports[2] = reply->sect_count;
+       req_task->io_ports[3] = reply->lba_low;
+       req_task->io_ports[4] = reply->lba_mid;
+       req_task->io_ports[5] = reply->lba_hi;
+       req_task->io_ports[6] = reply->device;
+
+       if (req_task->out_flags.all & 1)  {
+
+               req_task->hob_ports[3] = reply->lba_low_ex;
+               req_task->hob_ports[4] = reply->lba_mid_ex;
+               req_task->hob_ports[5] = reply->lba_hi_ex;
+               req_task->hob_ports[1] = reply->features_ex;
+               req_task->hob_ports[2] = reply->sect_cnt_ex;
+       }
+
+       /* Com rest after secure erase or lowlevel format */
+       if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) ||
+               ((fis.command == 0xFC) &&
+                       (fis.features == 0x27 || fis.features == 0x72 ||
+                        fis.features == 0x62 || fis.features == 0x26))) &&
+                        !(reply->command & 1)) {
+               mtip_restart_port(dd->port);
+       }
+
+       dbg_printk(MTIP_DRV_NAME
+               "%s: Completion: stat %x,"
+               "err %x, sect_cnt %x, lbalo %x,"
+               "lbamid %x, lbahi %x, dev %x\n",
+               __func__,
+               req_task->io_ports[7],
+               req_task->io_ports[1],
+               req_task->io_ports[2],
+               req_task->io_ports[3],
+               req_task->io_ports[4],
+               req_task->io_ports[5],
+               req_task->io_ports[6]);
+
+       if (taskout) {
+               if (copy_to_user(buf + outtotal, outbuf, taskout)) {
+                       err = -EFAULT;
+                       goto abort;
+               }
+       }
+       if (taskin) {
+               if (copy_to_user(buf + intotal, inbuf, taskin)) {
+                       err = -EFAULT;
+                       goto abort;
+               }
+       }
+abort:
+       if (inbuf_dma)
+               pci_unmap_single(dd->pdev, inbuf_dma,
+                                       taskin, DMA_FROM_DEVICE);
+       if (outbuf_dma)
+               pci_unmap_single(dd->pdev, outbuf_dma,
+                                       taskout, DMA_TO_DEVICE);
+       kfree(outbuf);
+       kfree(inbuf);
+
+       return err;
+}
+
+/*
+ * Handle IOCTL calls from the Block Layer.
+ *
+ * This function is called by the Block Layer when it receives an IOCTL
+ * command that it does not understand. If the IOCTL command is not supported
+ * this function returns -ENOTTY.
+ *
+ * @dd  Pointer to the driver data structure.
+ * @cmd IOCTL command passed from the Block Layer.
+ * @arg IOCTL argument passed from the Block Layer.
+ *
+ * return value
+ *     0       The IOCTL completed successfully.
+ *     -ENOTTY The specified command is not supported.
+ *     -EFAULT An error occurred copying data to a user space buffer.
+ *     -EIO    An error occurred while executing the command.
+ */
+static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
+                        unsigned long arg)
+{
+       switch (cmd) {
+       case HDIO_GET_IDENTITY:
+               if (mtip_get_identify(dd->port, (void __user *) arg) < 0) {
+                       dev_warn(&dd->pdev->dev,
+                               "Unable to read identity\n");
+                       return -EIO;
+               }
+
+               break;
+       case HDIO_DRIVE_CMD:
+       {
+               u8 drive_command[4];
+
+               /* Copy the user command info to our buffer. */
+               if (copy_from_user(drive_command,
+                                        (void __user *) arg,
+                                        sizeof(drive_command)))
+                       return -EFAULT;
+
+               /* Execute the drive command. */
+               if (exec_drive_command(dd->port,
+                                        drive_command,
+                                        (void __user *) (arg+4)))
+                       return -EIO;
+
+               /* Copy the status back to the users buffer. */
+               if (copy_to_user((void __user *) arg,
+                                        drive_command,
+                                        sizeof(drive_command)))
+                       return -EFAULT;
+
+               break;
+       }
+       case HDIO_DRIVE_TASK:
+       {
+               u8 drive_command[7];
+
+               /* Copy the user command info to our buffer. */
+               if (copy_from_user(drive_command,
+                                        (void __user *) arg,
+                                        sizeof(drive_command)))
+                       return -EFAULT;
+
+               /* Execute the drive command. */
+               if (exec_drive_task(dd->port, drive_command))
+                       return -EIO;
+
+               /* Copy the status back to the users buffer. */
+               if (copy_to_user((void __user *) arg,
+                                        drive_command,
+                                        sizeof(drive_command)))
+                       return -EFAULT;
+
+               break;
+       }
+       case HDIO_DRIVE_TASKFILE: {
+               ide_task_request_t req_task;
+               int ret, outtotal;
+
+               if (copy_from_user(&req_task, (void __user *) arg,
+                                       sizeof(req_task)))
+                       return -EFAULT;
+
+               outtotal = sizeof(req_task);
+
+               ret = exec_drive_taskfile(dd, (void __user *) arg,
+                                               &req_task, outtotal);
+
+               if (copy_to_user((void __user *) arg, &req_task,
+                                                       sizeof(req_task)))
+                       return -EFAULT;
+
+               return ret;
+       }
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * Submit an IO to the hw
+ *
+ * This function is called by the block layer to issue an io
+ * to the device. Upon completion, the callback function will
+ * be called with the data parameter passed as the callback data.
+ *
+ * @dd       Pointer to the driver data structure.
+ * @start    First sector to read.
+ * @nsect    Number of sectors to read.
+ * @nents    Number of entries in scatter list for the read command.
+ * @tag      The tag of this read command.
+ * @callback Pointer to the function that should be called
+ *          when the read completes.
+ * @data     Callback data passed to the callback function
+ *          when the read completes.
+ * @barrier  If non-zero, this command must be completed before
+ *          issuing any other commands.
+ * @dir      Direction (read or write)
+ *
+ * return value
+ *     None
+ */
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+                             int nsect, int nents, int tag, void *callback,
+                             void *data, int barrier, int dir)
+{
+       struct host_to_dev_fis  *fis;
+       struct mtip_port *port = dd->port;
+       struct mtip_cmd *command = &port->commands[tag];
+
+       /* Map the scatter list for DMA access */
+       if (dir == READ)
+               nents = dma_map_sg(&dd->pdev->dev, command->sg,
+                                       nents, DMA_FROM_DEVICE);
+       else
+               nents = dma_map_sg(&dd->pdev->dev, command->sg,
+                                       nents, DMA_TO_DEVICE);
+
+       command->scatter_ents = nents;
+
+       /*
+        * The number of retries for this command before it is
+        * reported as a failure to the upper layers.
+        */
+       command->retries = MTIP_MAX_RETRIES;
+
+       /* Fill out fis */
+       fis = command->command;
+       fis->type        = 0x27;
+       fis->opts        = 1 << 7;
+       fis->command     =
+               (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
+       *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
+       *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+       fis->device      = 1 << 6;
+       if (barrier)
+               fis->device |= FUA_BIT;
+       fis->features    = nsect & 0xFF;
+       fis->features_ex = (nsect >> 8) & 0xFF;
+       fis->sect_count  = ((tag << 3) | (tag >> 5));
+       fis->sect_cnt_ex = 0;
+       fis->control     = 0;
+       fis->res2        = 0;
+       fis->res3        = 0;
+       fill_command_sg(dd, command, nents);
+
+       /* Populate the command header */
+       command->command_header->opts =
+                       __force_bit2int cpu_to_le32(
+                               (nents << 16) | 5 | AHCI_CMD_PREFETCH);
+       command->command_header->byte_count = 0;
+
+       /*
+        * Set the completion function and data for the command
+        * within this layer.
+        */
+       command->comp_data = dd;
+       command->comp_func = mtip_async_complete;
+       command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+
+       /*
+        * Set the completion function and data for the command passed
+        * from the upper layer.
+        */
+       command->async_data = data;
+       command->async_callback = callback;
+
+       /*
+        * To prevent this command from being issued
+        * if an internal command is in progress or error handling is active.
+        */
+       if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) ||
+                       test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) {
+               set_bit(tag, port->cmds_to_issue);
+               set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+               return;
+       }
+
+       /* Issue the command to the hardware */
+       mtip_issue_ncq_command(port, tag);
+
+       /* Set the command's timeout value.*/
+       port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
+                                       MTIP_NCQ_COMMAND_TIMEOUT_MS);
+}
+
+/*
+ * Release a command slot.
+ *
+ * @dd  Pointer to the driver data structure.
+ * @tag Slot tag
+ *
+ * return value
+ *      None
+ */
+static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag)
+{
+       release_slot(dd->port, tag);
+}
+
+/*
+ * Obtain a command slot and return its associated scatter list.
+ *
+ * @dd  Pointer to the driver data structure.
+ * @tag Pointer to an int that will receive the allocated command
+ *            slot tag.
+ *
+ * return value
+ *     Pointer to the scatter list for the allocated command slot
+ *     or NULL if no command slots are available.
+ */
+static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
+                                                  int *tag)
+{
+       /*
+        * It is possible that, even with this semaphore, a thread
+        * may think that no command slots are available. Therefore, we
+        * need to make an attempt to get_slot().
+        */
+       down(&dd->port->cmd_slot);
+       *tag = get_slot(dd->port);
+
+       if (unlikely(*tag < 0))
+               return NULL;
+
+       return dd->port->commands[*tag].sg;
+}
+
+/*
+ * Sysfs register/status dump.
+ *
+ * @dev  Pointer to the device structure, passed by the kernrel.
+ * @attr Pointer to the device_attribute structure passed by the kernel.
+ * @buf  Pointer to the char buffer that will receive the stats info.
+ *
+ * return value
+ *     The size, in bytes, of the data copied into buf.
+ */
+static ssize_t hw_show_registers(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       u32 group_allocated;
+       struct driver_data *dd = dev_to_disk(dev)->private_data;
+       int size = 0;
+       int n;
+
+       size += sprintf(&buf[size], "%s:\ns_active:\n", __func__);
+
+       for (n = 0; n < dd->slot_groups; n++)
+               size += sprintf(&buf[size], "0x%08x\n",
+                                        readl(dd->port->s_active[n]));
+
+       size += sprintf(&buf[size], "Command Issue:\n");
+
+       for (n = 0; n < dd->slot_groups; n++)
+               size += sprintf(&buf[size], "0x%08x\n",
+                                       readl(dd->port->cmd_issue[n]));
+
+       size += sprintf(&buf[size], "Allocated:\n");
+
+       for (n = 0; n < dd->slot_groups; n++) {
+               if (sizeof(long) > sizeof(u32))
+                       group_allocated =
+                               dd->port->allocated[n/2] >> (32*(n&1));
+               else
+                       group_allocated = dd->port->allocated[n];
+               size += sprintf(&buf[size], "0x%08x\n",
+                                group_allocated);
+       }
+
+       size += sprintf(&buf[size], "completed:\n");
+
+       for (n = 0; n < dd->slot_groups; n++)
+               size += sprintf(&buf[size], "0x%08x\n",
+                               readl(dd->port->completed[n]));
+
+       size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n",
+                               readl(dd->port->mmio + PORT_IRQ_STAT));
+       size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n",
+                               readl(dd->mmio + HOST_IRQ_STAT));
+
+       return size;
+}
+static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL);
+
+/*
+ * Create the sysfs related attributes.
+ *
+ * @dd   Pointer to the driver data structure.
+ * @kobj Pointer to the kobj for the block device.
+ *
+ * return value
+ *     0       Operation completed successfully.
+ *     -EINVAL Invalid parameter.
+ */
+static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj)
+{
+       if (!kobj || !dd)
+               return -EINVAL;
+
+       if (sysfs_create_file(kobj, &dev_attr_registers.attr))
+               dev_warn(&dd->pdev->dev,
+                       "Error creating registers sysfs entry\n");
+       return 0;
+}
+
+/*
+ * Remove the sysfs related attributes.
+ *
+ * @dd   Pointer to the driver data structure.
+ * @kobj Pointer to the kobj for the block device.
+ *
+ * return value
+ *     0       Operation completed successfully.
+ *     -EINVAL Invalid parameter.
+ */
+static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj)
+{
+       if (!kobj || !dd)
+               return -EINVAL;
+
+       sysfs_remove_file(kobj, &dev_attr_registers.attr);
+
+       return 0;
+}
+
+/*
+ * Perform any init/resume time hardware setup
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     None
+ */
+static inline void hba_setup(struct driver_data *dd)
+{
+       u32 hwdata;
+       hwdata = readl(dd->mmio + HOST_HSORG);
+
+       /* interrupt bug workaround: use only 1 IS bit.*/
+       writel(hwdata |
+               HSORG_DISABLE_SLOTGRP_INTR |
+               HSORG_DISABLE_SLOTGRP_PXIS,
+               dd->mmio + HOST_HSORG);
+}
+
+/*
+ * Detect the details of the product, and store anything needed
+ * into the driver data structure.  This includes product type and
+ * version and number of slot groups.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     None
+ */
+static void mtip_detect_product(struct driver_data *dd)
+{
+       u32 hwdata;
+       unsigned int rev, slotgroups;
+
+       /*
+        * HBA base + 0xFC [15:0] - vendor-specific hardware interface
+        * info register:
+        * [15:8] hardware/software interface rev#
+        * [   3] asic-style interface
+        * [ 2:0] number of slot groups, minus 1 (only valid for asic-style).
+        */
+       hwdata = readl(dd->mmio + HOST_HSORG);
+
+       dd->product_type = MTIP_PRODUCT_UNKNOWN;
+       dd->slot_groups = 1;
+
+       if (hwdata & 0x8) {
+               dd->product_type = MTIP_PRODUCT_ASICFPGA;
+               rev = (hwdata & HSORG_HWREV) >> 8;
+               slotgroups = (hwdata & HSORG_SLOTGROUPS) + 1;
+               dev_info(&dd->pdev->dev,
+                       "ASIC-FPGA design, HS rev 0x%x, "
+                       "%i slot groups [%i slots]\n",
+                        rev,
+                        slotgroups,
+                        slotgroups * 32);
+
+               if (slotgroups > MTIP_MAX_SLOT_GROUPS) {
+                       dev_warn(&dd->pdev->dev,
+                               "Warning: driver only supports "
+                               "%i slot groups.\n", MTIP_MAX_SLOT_GROUPS);
+                       slotgroups = MTIP_MAX_SLOT_GROUPS;
+               }
+               dd->slot_groups = slotgroups;
+               return;
+       }
+
+       dev_warn(&dd->pdev->dev, "Unrecognized product id\n");
+}
+
+/*
+ * Blocking wait for FTL rebuild to complete
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ *     0       FTL rebuild completed successfully
+ *     -EFAULT FTL rebuild error/timeout/interruption
+ */
+static int mtip_ftl_rebuild_poll(struct driver_data *dd)
+{
+       unsigned long timeout, cnt = 0, start;
+
+       dev_warn(&dd->pdev->dev,
+               "FTL rebuild in progress. Polling for completion.\n");
+
+       start = jiffies;
+       dd->ftlrebuildflag = 1;
+       timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS);
+
+       do {
+               if (mtip_check_surprise_removal(dd->pdev))
+                       return -EFAULT;
+
+               if (mtip_get_identify(dd->port, NULL) < 0)
+                       return -EFAULT;
+
+               if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
+                       MTIP_FTL_REBUILD_MAGIC) {
+                       ssleep(1);
+                       /* Print message every 3 minutes */
+                       if (cnt++ >= 180) {
+                               dev_warn(&dd->pdev->dev,
+                               "FTL rebuild in progress (%d secs).\n",
+                               jiffies_to_msecs(jiffies - start) / 1000);
+                               cnt = 0;
+                       }
+               } else {
+                       dev_warn(&dd->pdev->dev,
+                               "FTL rebuild complete (%d secs).\n",
+                       jiffies_to_msecs(jiffies - start) / 1000);
+                       dd->ftlrebuildflag = 0;
+                       mtip_block_initialize(dd);
+                       break;
+               }
+               ssleep(10);
+       } while (time_before(jiffies, timeout));
+
+       /* Check for timeout */
+       if (dd->ftlrebuildflag) {
+               dev_err(&dd->pdev->dev,
+               "Timed out waiting for FTL rebuild to complete (%d secs).\n",
+               jiffies_to_msecs(jiffies - start) / 1000);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*
+ * service thread to issue queued commands
+ *
+ * @data Pointer to the driver data structure.
+ *
+ * return value
+ *     0
+ */
+
+static int mtip_service_thread(void *data)
+{
+       struct driver_data *dd = (struct driver_data *)data;
+       unsigned long slot, slot_start, slot_wrap;
+       unsigned int num_cmd_slots = dd->slot_groups * 32;
+       struct mtip_port *port = dd->port;
+
+       while (1) {
+               /*
+                * the condition is to check neither an internal command is
+                * is in progress nor error handling is active
+                */
+               wait_event_interruptible(port->svc_wait, (port->flags) &&
+                       !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+                       !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags));
+
+               if (kthread_should_stop())
+                       break;
+
+               set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+               if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+                       slot = 1;
+                       /* used to restrict the loop to one iteration */
+                       slot_start = num_cmd_slots;
+                       slot_wrap = 0;
+                       while (1) {
+                               slot = find_next_bit(port->cmds_to_issue,
+                                               num_cmd_slots, slot);
+                               if (slot_wrap == 1) {
+                                       if ((slot_start >= slot) ||
+                                               (slot >= num_cmd_slots))
+                                               break;
+                               }
+                               if (unlikely(slot_start == num_cmd_slots))
+                                       slot_start = slot;
+
+                               if (unlikely(slot == num_cmd_slots)) {
+                                       slot = 1;
+                                       slot_wrap = 1;
+                                       continue;
+                               }
+
+                               /* Issue the command to the hardware */
+                               mtip_issue_ncq_command(port, slot);
+
+                               /* Set the command's timeout value.*/
+                               port->commands[slot].comp_time = jiffies +
+                               msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS);
+
+                               clear_bit(slot, port->cmds_to_issue);
+                       }
+
+                       clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+               } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) {
+                       mtip_ftl_rebuild_poll(dd);
+                       clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags);
+               }
+               clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+
+               if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags))
+                       break;
+       }
+       return 0;
+}
+
+/*
+ * Called once for each card.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0 on success, else an error code.
+ */
+static int mtip_hw_init(struct driver_data *dd)
+{
+       int i;
+       int rv;
+       unsigned int num_command_slots;
+
+       dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
+
+       mtip_detect_product(dd);
+       if (dd->product_type == MTIP_PRODUCT_UNKNOWN) {
+               rv = -EIO;
+               goto out1;
+       }
+       num_command_slots = dd->slot_groups * 32;
+
+       hba_setup(dd);
+
+       tasklet_init(&dd->tasklet, mtip_tasklet, (unsigned long)dd);
+
+       dd->port = kzalloc(sizeof(struct mtip_port), GFP_KERNEL);
+       if (!dd->port) {
+               dev_err(&dd->pdev->dev,
+                       "Memory allocation: port structure\n");
+               return -ENOMEM;
+       }
+
+       /* Counting semaphore to track command slot usage */
+       sema_init(&dd->port->cmd_slot, num_command_slots - 1);
+
+       /* Spinlock to prevent concurrent issue */
+       spin_lock_init(&dd->port->cmd_issue_lock);
+
+       /* Set the port mmio base address. */
+       dd->port->mmio  = dd->mmio + PORT_OFFSET;
+       dd->port->dd    = dd;
+
+       /* Allocate memory for the command list. */
+       dd->port->command_list =
+               dmam_alloc_coherent(&dd->pdev->dev,
+                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                       &dd->port->command_list_dma,
+                       GFP_KERNEL);
+       if (!dd->port->command_list) {
+               dev_err(&dd->pdev->dev,
+                       "Memory allocation: command list\n");
+               rv = -ENOMEM;
+               goto out1;
+       }
+
+       /* Clear the memory we have allocated. */
+       memset(dd->port->command_list,
+               0,
+               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2));
+
+       /* Setup the addresse of the RX FIS. */
+       dd->port->rxfis     = dd->port->command_list + HW_CMD_SLOT_SZ;
+       dd->port->rxfis_dma = dd->port->command_list_dma + HW_CMD_SLOT_SZ;
+
+       /* Setup the address of the command tables. */
+       dd->port->command_table   = dd->port->rxfis + AHCI_RX_FIS_SZ;
+       dd->port->command_tbl_dma = dd->port->rxfis_dma + AHCI_RX_FIS_SZ;
+
+       /* Setup the address of the identify data. */
+       dd->port->identify     = dd->port->command_table +
+                                       HW_CMD_TBL_AR_SZ;
+       dd->port->identify_dma = dd->port->command_tbl_dma +
+                                       HW_CMD_TBL_AR_SZ;
+
+       /* Setup the address of the sector buffer. */
+       dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE;
+       dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE;
+
+       /* Point the command headers at the command tables. */
+       for (i = 0; i < num_command_slots; i++) {
+               dd->port->commands[i].command_header =
+                                       dd->port->command_list +
+                                       (sizeof(struct mtip_cmd_hdr) * i);
+               dd->port->commands[i].command_header_dma =
+                                       dd->port->command_list_dma +
+                                       (sizeof(struct mtip_cmd_hdr) * i);
+
+               dd->port->commands[i].command =
+                       dd->port->command_table + (HW_CMD_TBL_SZ * i);
+               dd->port->commands[i].command_dma =
+                       dd->port->command_tbl_dma + (HW_CMD_TBL_SZ * i);
+
+               if (readl(dd->mmio + HOST_CAP) & HOST_CAP_64)
+                       dd->port->commands[i].command_header->ctbau =
+                       __force_bit2int cpu_to_le32(
+                       (dd->port->commands[i].command_dma >> 16) >> 16);
+               dd->port->commands[i].command_header->ctba =
+                       __force_bit2int cpu_to_le32(
+                       dd->port->commands[i].command_dma & 0xFFFFFFFF);
+
+               /*
+                * If this is not done, a bug is reported by the stock
+                * FC11 i386. Due to the fact that it has lots of kernel
+                * debugging enabled.
+                */
+               sg_init_table(dd->port->commands[i].sg, MTIP_MAX_SG);
+
+               /* Mark all commands as currently inactive.*/
+               atomic_set(&dd->port->commands[i].active, 0);
+       }
+
+       /* Setup the pointers to the extended s_active and CI registers. */
+       for (i = 0; i < dd->slot_groups; i++) {
+               dd->port->s_active[i] =
+                       dd->port->mmio + i*0x80 + PORT_SCR_ACT;
+               dd->port->cmd_issue[i] =
+                       dd->port->mmio + i*0x80 + PORT_COMMAND_ISSUE;
+               dd->port->completed[i] =
+                       dd->port->mmio + i*0x80 + PORT_SDBV;
+       }
+
+       /* Reset the HBA. */
+       if (mtip_hba_reset(dd) < 0) {
+               dev_err(&dd->pdev->dev,
+                       "Card did not reset within timeout\n");
+               rv = -EIO;
+               goto out2;
+       }
+
+       mtip_init_port(dd->port);
+       mtip_start_port(dd->port);
+
+       /* Setup the ISR and enable interrupts. */
+       rv = devm_request_irq(&dd->pdev->dev,
+                               dd->pdev->irq,
+                               mtip_irq_handler,
+                               IRQF_SHARED,
+                               dev_driver_string(&dd->pdev->dev),
+                               dd);
+
+       if (rv) {
+               dev_err(&dd->pdev->dev,
+                       "Unable to allocate IRQ %d\n", dd->pdev->irq);
+               goto out2;
+       }
+
+       /* Enable interrupts on the HBA. */
+       writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+                                       dd->mmio + HOST_CTL);
+
+       init_timer(&dd->port->cmd_timer);
+       init_waitqueue_head(&dd->port->svc_wait);
+
+       dd->port->cmd_timer.data = (unsigned long int) dd->port;
+       dd->port->cmd_timer.function = mtip_timeout_function;
+       mod_timer(&dd->port->cmd_timer,
+               jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+
+       if (mtip_get_identify(dd->port, NULL) < 0) {
+               rv = -EFAULT;
+               goto out3;
+       }
+
+       if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
+               MTIP_FTL_REBUILD_MAGIC) {
+               set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags);
+               return MTIP_FTL_REBUILD_MAGIC;
+       }
+       mtip_dump_identify(dd->port);
+       return rv;
+
+out3:
+       del_timer_sync(&dd->port->cmd_timer);
+
+       /* Disable interrupts on the HBA. */
+       writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+                       dd->mmio + HOST_CTL);
+
+       /*Release the IRQ. */
+       devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
+
+out2:
+       mtip_deinit_port(dd->port);
+
+       /* Free the command/command header memory. */
+       dmam_free_coherent(&dd->pdev->dev,
+                               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                               dd->port->command_list,
+                               dd->port->command_list_dma);
+out1:
+       /* Free the memory allocated for the for structure. */
+       kfree(dd->port);
+
+       return rv;
+}
+
+/*
+ * Called to deinitialize an interface.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0
+ */
+static int mtip_hw_exit(struct driver_data *dd)
+{
+       /*
+        * Send standby immediate (E0h) to the drive so that it
+        * saves its state.
+        */
+       if (atomic_read(&dd->drv_cleanup_done) != true) {
+
+               mtip_standby_immediate(dd->port);
+
+               /* de-initialize the port. */
+               mtip_deinit_port(dd->port);
+
+               /* Disable interrupts on the HBA. */
+               writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+                               dd->mmio + HOST_CTL);
+       }
+
+       del_timer_sync(&dd->port->cmd_timer);
+
+       /* Release the IRQ. */
+       devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
+
+       /* Stop the bottom half tasklet. */
+       tasklet_kill(&dd->tasklet);
+
+       /* Free the command/command header memory. */
+       dmam_free_coherent(&dd->pdev->dev,
+                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                       dd->port->command_list,
+                       dd->port->command_list_dma);
+       /* Free the memory allocated for the for structure. */
+       kfree(dd->port);
+
+       return 0;
+}
+
+/*
+ * Issue a Standby Immediate command to the device.
+ *
+ * This function is called by the Block Layer just before the
+ * system powers off during a shutdown.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0
+ */
+static int mtip_hw_shutdown(struct driver_data *dd)
+{
+       /*
+        * Send standby immediate (E0h) to the drive so that it
+        * saves its state.
+        */
+       mtip_standby_immediate(dd->port);
+
+       return 0;
+}
+
+/*
+ * Suspend function
+ *
+ * This function is called by the Block Layer just before the
+ * system hibernates.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0       Suspend was successful
+ *     -EFAULT Suspend was not successful
+ */
+static int mtip_hw_suspend(struct driver_data *dd)
+{
+       /*
+        * Send standby immediate (E0h) to the drive
+        * so that it saves its state.
+        */
+       if (mtip_standby_immediate(dd->port) != 0) {
+               dev_err(&dd->pdev->dev,
+                       "Failed standby-immediate command\n");
+               return -EFAULT;
+       }
+
+       /* Disable interrupts on the HBA.*/
+       writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+                       dd->mmio + HOST_CTL);
+       mtip_deinit_port(dd->port);
+
+       return 0;
+}
+
+/*
+ * Resume function
+ *
+ * This function is called by the Block Layer as the
+ * system resumes.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0       Resume was successful
+ *      -EFAULT Resume was not successful
+ */
+static int mtip_hw_resume(struct driver_data *dd)
+{
+       /* Perform any needed hardware setup steps */
+       hba_setup(dd);
+
+       /* Reset the HBA */
+       if (mtip_hba_reset(dd) != 0) {
+               dev_err(&dd->pdev->dev,
+                       "Unable to reset the HBA\n");
+               return -EFAULT;
+       }
+
+       /*
+        * Enable the port, DMA engine, and FIS reception specific
+        * h/w in controller.
+        */
+       mtip_init_port(dd->port);
+       mtip_start_port(dd->port);
+
+       /* Enable interrupts on the HBA.*/
+       writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+                       dd->mmio + HOST_CTL);
+
+       return 0;
+}
+
+/*
+ * Helper function for reusing disk name
+ * upon hot insertion.
+ */
+static int rssd_disk_name_format(char *prefix,
+                                int index,
+                                char *buf,
+                                int buflen)
+{
+       const int base = 'z' - 'a' + 1;
+       char *begin = buf + strlen(prefix);
+       char *end = buf + buflen;
+       char *p;
+       int unit;
+
+       p = end - 1;
+       *p = '\0';
+       unit = base;
+       do {
+               if (p == begin)
+                       return -EINVAL;
+               *--p = 'a' + (index % unit);
+               index = (index / unit) - 1;
+       } while (index >= 0);
+
+       memmove(begin, p, end - p);
+       memcpy(buf, prefix, strlen(prefix));
+
+       return 0;
+}
+
+/*
+ * Block layer IOCTL handler.
+ *
+ * @dev Pointer to the block_device structure.
+ * @mode ignored
+ * @cmd IOCTL command passed from the user application.
+ * @arg Argument passed from the user application.
+ *
+ * return value
+ *     0        IOCTL completed successfully.
+ *     -ENOTTY  IOCTL not supported or invalid driver data
+ *                 structure pointer.
+ */
+static int mtip_block_ioctl(struct block_device *dev,
+                           fmode_t mode,
+                           unsigned cmd,
+                           unsigned long arg)
+{
+       struct driver_data *dd = dev->bd_disk->private_data;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (!dd)
+               return -ENOTTY;
+
+       switch (cmd) {
+       case BLKFLSBUF:
+               return -ENOTTY;
+       default:
+               return mtip_hw_ioctl(dd, cmd, arg);
+       }
+}
+
+#ifdef CONFIG_COMPAT
+/*
+ * Block layer compat IOCTL handler.
+ *
+ * @dev Pointer to the block_device structure.
+ * @mode ignored
+ * @cmd IOCTL command passed from the user application.
+ * @arg Argument passed from the user application.
+ *
+ * return value
+ *     0        IOCTL completed successfully.
+ *     -ENOTTY  IOCTL not supported or invalid driver data
+ *                 structure pointer.
+ */
+static int mtip_block_compat_ioctl(struct block_device *dev,
+                           fmode_t mode,
+                           unsigned cmd,
+                           unsigned long arg)
+{
+       struct driver_data *dd = dev->bd_disk->private_data;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (!dd)
+               return -ENOTTY;
+
+       switch (cmd) {
+       case BLKFLSBUF:
+               return -ENOTTY;
+       case HDIO_DRIVE_TASKFILE: {
+               struct mtip_compat_ide_task_request_s __user *compat_req_task;
+               ide_task_request_t req_task;
+               int compat_tasksize, outtotal, ret;
+
+               compat_tasksize =
+                       sizeof(struct mtip_compat_ide_task_request_s);
+
+               compat_req_task =
+                       (struct mtip_compat_ide_task_request_s __user *) arg;
+
+               if (copy_from_user(&req_task, (void __user *) arg,
+                       compat_tasksize - (2 * sizeof(compat_long_t))))
+                       return -EFAULT;
+
+               if (get_user(req_task.out_size, &compat_req_task->out_size))
+                       return -EFAULT;
+
+               if (get_user(req_task.in_size, &compat_req_task->in_size))
+                       return -EFAULT;
+
+               outtotal = sizeof(struct mtip_compat_ide_task_request_s);
+
+               ret = exec_drive_taskfile(dd, (void __user *) arg,
+                                               &req_task, outtotal);
+
+               if (copy_to_user((void __user *) arg, &req_task,
+                               compat_tasksize -
+                               (2 * sizeof(compat_long_t))))
+                       return -EFAULT;
+
+               if (put_user(req_task.out_size, &compat_req_task->out_size))
+                       return -EFAULT;
+
+               if (put_user(req_task.in_size, &compat_req_task->in_size))
+                       return -EFAULT;
+
+               return ret;
+       }
+       default:
+               return mtip_hw_ioctl(dd, cmd, arg);
+       }
+}
+#endif
+
+/*
+ * Obtain the geometry of the device.
+ *
+ * You may think that this function is obsolete, but some applications,
+ * fdisk for example still used CHS values. This function describes the
+ * device as having 224 heads and 56 sectors per cylinder. These values are
+ * chosen so that each cylinder is aligned on a 4KB boundary. Since a
+ * partition is described in terms of a start and end cylinder this means
+ * that each partition is also 4KB aligned. Non-aligned partitions adversely
+ * affects performance.
+ *
+ * @dev Pointer to the block_device strucutre.
+ * @geo Pointer to a hd_geometry structure.
+ *
+ * return value
+ *     0       Operation completed successfully.
+ *     -ENOTTY An error occurred while reading the drive capacity.
+ */
+static int mtip_block_getgeo(struct block_device *dev,
+                               struct hd_geometry *geo)
+{
+       struct driver_data *dd = dev->bd_disk->private_data;
+       sector_t capacity;
+
+       if (!dd)
+               return -ENOTTY;
+
+       if (!(mtip_hw_get_capacity(dd, &capacity))) {
+               dev_warn(&dd->pdev->dev,
+                       "Could not get drive capacity.\n");
+               return -ENOTTY;
+       }
+
+       geo->heads = 224;
+       geo->sectors = 56;
+       sector_div(capacity, (geo->heads * geo->sectors));
+       geo->cylinders = capacity;
+       return 0;
+}
+
+/*
+ * Block device operation function.
+ *
+ * This structure contains pointers to the functions required by the block
+ * layer.
+ */
+static const struct block_device_operations mtip_block_ops = {
+       .ioctl          = mtip_block_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = mtip_block_compat_ioctl,
+#endif
+       .getgeo         = mtip_block_getgeo,
+       .owner          = THIS_MODULE
+};
+
+/*
+ * Block layer make request function.
+ *
+ * This function is called by the kernel to process a BIO for
+ * the P320 device.
+ *
+ * @queue Pointer to the request queue. Unused other than to obtain
+ *              the driver data structure.
+ * @bio   Pointer to the BIO.
+ *
+ */
+static void mtip_make_request(struct request_queue *queue, struct bio *bio)
+{
+       struct driver_data *dd = queue->queuedata;
+       struct scatterlist *sg;
+       struct bio_vec *bvec;
+       int nents = 0;
+       int tag = 0;
+
+       if (unlikely(!bio_has_data(bio))) {
+               blk_queue_flush(queue, 0);
+               bio_endio(bio, 0);
+               return;
+       }
+
+       sg = mtip_hw_get_scatterlist(dd, &tag);
+       if (likely(sg != NULL)) {
+               blk_queue_bounce(queue, &bio);
+
+               if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
+                       dev_warn(&dd->pdev->dev,
+                               "Maximum number of SGL entries exceeded");
+                       bio_io_error(bio);
+                       mtip_hw_release_scatterlist(dd, tag);
+                       return;
+               }
+
+               /* Create the scatter list for this bio. */
+               bio_for_each_segment(bvec, bio, nents) {
+                       sg_set_page(&sg[nents],
+                                       bvec->bv_page,
+                                       bvec->bv_len,
+                                       bvec->bv_offset);
+               }
+
+               /* Issue the read/write. */
+               mtip_hw_submit_io(dd,
+                               bio->bi_sector,
+                               bio_sectors(bio),
+                               nents,
+                               tag,
+                               bio_endio,
+                               bio,
+                               bio->bi_rw & REQ_FUA,
+                               bio_data_dir(bio));
+       } else
+               bio_io_error(bio);
+}
+
+/*
+ * Block layer initialization function.
+ *
+ * This function is called once by the PCI layer for each P320
+ * device that is connected to the system.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0 on success else an error code.
+ */
+static int mtip_block_initialize(struct driver_data *dd)
+{
+       int rv = 0, wait_for_rebuild = 0;
+       sector_t capacity;
+       unsigned int index = 0;
+       struct kobject *kobj;
+       unsigned char thd_name[16];
+
+       if (dd->disk)
+               goto skip_create_disk; /* hw init done, before rebuild */
+
+       /* Initialize the protocol layer. */
+       wait_for_rebuild = mtip_hw_init(dd);
+       if (wait_for_rebuild < 0) {
+               dev_err(&dd->pdev->dev,
+                       "Protocol layer initialization failed\n");
+               rv = -EINVAL;
+               goto protocol_init_error;
+       }
+
+       dd->disk = alloc_disk(MTIP_MAX_MINORS);
+       if (dd->disk  == NULL) {
+               dev_err(&dd->pdev->dev,
+                       "Unable to allocate gendisk structure\n");
+               rv = -EINVAL;
+               goto alloc_disk_error;
+       }
+
+       /* Generate the disk name, implemented same as in sd.c */
+       do {
+               if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL))
+                       goto ida_get_error;
+
+               spin_lock(&rssd_index_lock);
+               rv = ida_get_new(&rssd_index_ida, &index);
+               spin_unlock(&rssd_index_lock);
+       } while (rv == -EAGAIN);
+
+       if (rv)
+               goto ida_get_error;
+
+       rv = rssd_disk_name_format("rssd",
+                               index,
+                               dd->disk->disk_name,
+                               DISK_NAME_LEN);
+       if (rv)
+               goto disk_index_error;
+
+       dd->disk->driverfs_dev  = &dd->pdev->dev;
+       dd->disk->major         = dd->major;
+       dd->disk->first_minor   = dd->instance * MTIP_MAX_MINORS;
+       dd->disk->fops          = &mtip_block_ops;
+       dd->disk->private_data  = dd;
+       dd->index               = index;
+
+       /*
+        * if rebuild pending, start the service thread, and delay the block
+        * queue creation and add_disk()
+        */
+       if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
+               goto start_service_thread;
+
+skip_create_disk:
+       /* Allocate the request queue. */
+       dd->queue = blk_alloc_queue(GFP_KERNEL);
+       if (dd->queue == NULL) {
+               dev_err(&dd->pdev->dev,
+                       "Unable to allocate request queue\n");
+               rv = -ENOMEM;
+               goto block_queue_alloc_init_error;
+       }
+
+       /* Attach our request function to the request queue. */
+       blk_queue_make_request(dd->queue, mtip_make_request);
+
+       dd->disk->queue         = dd->queue;
+       dd->queue->queuedata    = dd;
+
+       /* Set device limits. */
+       set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags);
+       blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
+       blk_queue_physical_block_size(dd->queue, 4096);
+       blk_queue_io_min(dd->queue, 4096);
+       blk_queue_flush(dd->queue, 0);
+
+       /* Set the capacity of the device in 512 byte sectors. */
+       if (!(mtip_hw_get_capacity(dd, &capacity))) {
+               dev_warn(&dd->pdev->dev,
+                       "Could not read drive capacity\n");
+               rv = -EIO;
+               goto read_capacity_error;
+       }
+       set_capacity(dd->disk, capacity);
+
+       /* Enable the block device and add it to /dev */
+       add_disk(dd->disk);
+
+       /*
+        * Now that the disk is active, initialize any sysfs attributes
+        * managed by the protocol layer.
+        */
+       kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+       if (kobj) {
+               mtip_hw_sysfs_init(dd, kobj);
+               kobject_put(kobj);
+       }
+
+       if (dd->mtip_svc_handler)
+               return rv; /* service thread created for handling rebuild */
+
+start_service_thread:
+       sprintf(thd_name, "mtip_svc_thd_%02d", index);
+
+       dd->mtip_svc_handler = kthread_run(mtip_service_thread,
+                                               dd, thd_name);
+
+       if (IS_ERR(dd->mtip_svc_handler)) {
+               printk(KERN_ERR "mtip32xx: service thread failed to start\n");
+               dd->mtip_svc_handler = NULL;
+               rv = -EFAULT;
+               goto kthread_run_error;
+       }
+
+       return rv;
+
+kthread_run_error:
+       /* Delete our gendisk. This also removes the device from /dev */
+       del_gendisk(dd->disk);
+
+read_capacity_error:
+       blk_cleanup_queue(dd->queue);
+
+block_queue_alloc_init_error:
+disk_index_error:
+       spin_lock(&rssd_index_lock);
+       ida_remove(&rssd_index_ida, index);
+       spin_unlock(&rssd_index_lock);
+
+ida_get_error:
+       put_disk(dd->disk);
+
+alloc_disk_error:
+       mtip_hw_exit(dd); /* De-initialize the protocol layer. */
+
+protocol_init_error:
+       return rv;
+}
+
+/*
+ * Block layer deinitialization function.
+ *
+ * Called by the PCI layer as each P320 device is removed.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0
+ */
+static int mtip_block_remove(struct driver_data *dd)
+{
+       struct kobject *kobj;
+
+       if (dd->mtip_svc_handler) {
+               set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags);
+               wake_up_interruptible(&dd->port->svc_wait);
+               kthread_stop(dd->mtip_svc_handler);
+       }
+
+       /* Clean up the sysfs attributes managed by the protocol layer. */
+       kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+       if (kobj) {
+               mtip_hw_sysfs_exit(dd, kobj);
+               kobject_put(kobj);
+       }
+
+       /*
+        * Delete our gendisk structure. This also removes the device
+        * from /dev
+        */
+       del_gendisk(dd->disk);
+       blk_cleanup_queue(dd->queue);
+       dd->disk  = NULL;
+       dd->queue = NULL;
+
+       /* De-initialize the protocol layer. */
+       mtip_hw_exit(dd);
+
+       return 0;
+}
+
+/*
+ * Function called by the PCI layer when just before the
+ * machine shuts down.
+ *
+ * If a protocol layer shutdown function is present it will be called
+ * by this function.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ *     0
+ */
+static int mtip_block_shutdown(struct driver_data *dd)
+{
+       dev_info(&dd->pdev->dev,
+               "Shutting down %s ...\n", dd->disk->disk_name);
+
+       /* Delete our gendisk structure, and cleanup the blk queue. */
+       del_gendisk(dd->disk);
+       blk_cleanup_queue(dd->queue);
+       dd->disk  = NULL;
+       dd->queue = NULL;
+
+       mtip_hw_shutdown(dd);
+       return 0;
+}
+
+static int mtip_block_suspend(struct driver_data *dd)
+{
+       dev_info(&dd->pdev->dev,
+               "Suspending %s ...\n", dd->disk->disk_name);
+       mtip_hw_suspend(dd);
+       return 0;
+}
+
+static int mtip_block_resume(struct driver_data *dd)
+{
+       dev_info(&dd->pdev->dev, "Resuming %s ...\n",
+               dd->disk->disk_name);
+       mtip_hw_resume(dd);
+       return 0;
+}
+
+/*
+ * Called for each supported PCI device detected.
+ *
+ * This function allocates the private data structure, enables the
+ * PCI device and then calls the block layer initialization function.
+ *
+ * return value
+ *     0 on success else an error code.
+ */
+static int mtip_pci_probe(struct pci_dev *pdev,
+                       const struct pci_device_id *ent)
+{
+       int rv = 0;
+       struct driver_data *dd = NULL;
+
+       /* Allocate memory for this devices private data. */
+       dd = kzalloc(sizeof(struct driver_data), GFP_KERNEL);
+       if (dd == NULL) {
+               dev_err(&pdev->dev,
+                       "Unable to allocate memory for driver data\n");
+               return -ENOMEM;
+       }
+
+       /* Set the atomic variable as 1 in case of SRSI */
+       atomic_set(&dd->drv_cleanup_done, true);
+
+       atomic_set(&dd->resumeflag, false);
+
+       /* Attach the private data to this PCI device.  */
+       pci_set_drvdata(pdev, dd);
+
+       rv = pcim_enable_device(pdev);
+       if (rv < 0) {
+               dev_err(&pdev->dev, "Unable to enable device\n");
+               goto iomap_err;
+       }
+
+       /* Map BAR5 to memory. */
+       rv = pcim_iomap_regions(pdev, 1 << MTIP_ABAR, MTIP_DRV_NAME);
+       if (rv < 0) {
+               dev_err(&pdev->dev, "Unable to map regions\n");
+               goto iomap_err;
+       }
+
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               rv = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+
+               if (rv) {
+                       rv = pci_set_consistent_dma_mask(pdev,
+                                               DMA_BIT_MASK(32));
+                       if (rv) {
+                               dev_warn(&pdev->dev,
+                                       "64-bit DMA enable failed\n");
+                               goto setmask_err;
+                       }
+               }
+       }
+
+       pci_set_master(pdev);
+
+       if (pci_enable_msi(pdev)) {
+               dev_warn(&pdev->dev,
+                       "Unable to enable MSI interrupt.\n");
+               goto block_initialize_err;
+       }
+
+       /* Copy the info we may need later into the private data structure. */
+       dd->major       = mtip_major;
+       dd->instance    = instance;
+       dd->pdev        = pdev;
+
+       /* Initialize the block layer. */
+       rv = mtip_block_initialize(dd);
+       if (rv < 0) {
+               dev_err(&pdev->dev,
+                       "Unable to initialize block layer\n");
+               goto block_initialize_err;
+       }
+
+       /*
+        * Increment the instance count so that each device has a unique
+        * instance number.
+        */
+       instance++;
+
+       goto done;
+
+block_initialize_err:
+       pci_disable_msi(pdev);
+
+setmask_err:
+       pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
+
+iomap_err:
+       kfree(dd);
+       pci_set_drvdata(pdev, NULL);
+       return rv;
+done:
+       /* Set the atomic variable as 0 in case of SRSI */
+       atomic_set(&dd->drv_cleanup_done, true);
+
+       return rv;
+}
+
+/*
+ * Called for each probed device when the device is removed or the
+ * driver is unloaded.
+ *
+ * return value
+ *     None
+ */
+static void mtip_pci_remove(struct pci_dev *pdev)
+{
+       struct driver_data *dd = pci_get_drvdata(pdev);
+       int counter = 0;
+
+       if (mtip_check_surprise_removal(pdev)) {
+               while (atomic_read(&dd->drv_cleanup_done) == false) {
+                       counter++;
+                       msleep(20);
+                       if (counter == 10) {
+                               /* Cleanup the outstanding commands */
+                               mtip_command_cleanup(dd);
+                               break;
+                       }
+               }
+       }
+       /* Set the atomic variable as 1 in case of SRSI */
+       atomic_set(&dd->drv_cleanup_done, true);
+
+       /* Clean up the block layer. */
+       mtip_block_remove(dd);
+
+       pci_disable_msi(pdev);
+
+       kfree(dd);
+       pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
+}
+
+/*
+ * Called for each probed device when the device is suspended.
+ *
+ * return value
+ *     0  Success
+ *     <0 Error
+ */
+static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       int rv = 0;
+       struct driver_data *dd = pci_get_drvdata(pdev);
+
+       if (!dd) {
+               dev_err(&pdev->dev,
+                       "Driver private datastructure is NULL\n");
+               return -EFAULT;
+       }
+
+       atomic_set(&dd->resumeflag, true);
+
+       /* Disable ports & interrupts then send standby immediate */
+       rv = mtip_block_suspend(dd);
+       if (rv < 0) {
+               dev_err(&pdev->dev,
+                       "Failed to suspend controller\n");
+               return rv;
+       }
+
+       /*
+        * Save the pci config space to pdev structure &
+        * disable the device
+        */
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+
+       /* Move to Low power state*/
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return rv;
+}
+
+/*
+ * Called for each probed device when the device is resumed.
+ *
+ * return value
+ *      0  Success
+ *      <0 Error
+ */
+static int mtip_pci_resume(struct pci_dev *pdev)
+{
+       int rv = 0;
+       struct driver_data *dd;
+
+       dd = pci_get_drvdata(pdev);
+       if (!dd) {
+               dev_err(&pdev->dev,
+                       "Driver private datastructure is NULL\n");
+               return -EFAULT;
+       }
+
+       /* Move the device to active State */
+       pci_set_power_state(pdev, PCI_D0);
+
+       /* Restore PCI configuration space */
+       pci_restore_state(pdev);
+
+       /* Enable the PCI device*/
+       rv = pcim_enable_device(pdev);
+       if (rv < 0) {
+               dev_err(&pdev->dev,
+                       "Failed to enable card during resume\n");
+               goto err;
+       }
+       pci_set_master(pdev);
+
+       /*
+        * Calls hbaReset, initPort, & startPort function
+        * then enables interrupts
+        */
+       rv = mtip_block_resume(dd);
+       if (rv < 0)
+               dev_err(&pdev->dev, "Unable to resume\n");
+
+err:
+       atomic_set(&dd->resumeflag, false);
+
+       return rv;
+}
+
+/*
+ * Shutdown routine
+ *
+ * return value
+ *      None
+ */
+static void mtip_pci_shutdown(struct pci_dev *pdev)
+{
+       struct driver_data *dd = pci_get_drvdata(pdev);
+       if (dd)
+               mtip_block_shutdown(dd);
+}
+
+/* Table of device ids supported by this driver. */
+static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
+       {  PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) },
+       { 0 }
+};
+
+/* Structure that describes the PCI driver functions. */
+static struct pci_driver mtip_pci_driver = {
+       .name                   = MTIP_DRV_NAME,
+       .id_table               = mtip_pci_tbl,
+       .probe                  = mtip_pci_probe,
+       .remove                 = mtip_pci_remove,
+       .suspend                = mtip_pci_suspend,
+       .resume                 = mtip_pci_resume,
+       .shutdown               = mtip_pci_shutdown,
+};
+
+MODULE_DEVICE_TABLE(pci, mtip_pci_tbl);
+
+/*
+ * Module initialization function.
+ *
+ * Called once when the module is loaded. This function allocates a major
+ * block device number to the Cyclone devices and registers the PCI layer
+ * of the driver.
+ *
+ * Return value
+ *      0 on success else error code.
+ */
+static int __init mtip_init(void)
+{
+       printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
+
+       /* Allocate a major block device number to use with this driver. */
+       mtip_major = register_blkdev(0, MTIP_DRV_NAME);
+       if (mtip_major < 0) {
+               printk(KERN_ERR "Unable to register block device (%d)\n",
+               mtip_major);
+               return -EBUSY;
+       }
+
+       /* Register our PCI operations. */
+       return pci_register_driver(&mtip_pci_driver);
+}
+
+/*
+ * Module de-initialization function.
+ *
+ * Called once when the module is unloaded. This function deallocates
+ * the major block device number allocated by mtip_init() and
+ * unregisters the PCI layer of the driver.
+ *
+ * Return value
+ *      none
+ */
+static void __exit mtip_exit(void)
+{
+       /* Release the allocated major block device number. */
+       unregister_blkdev(mtip_major, MTIP_DRV_NAME);
+
+       /* Unregister the PCI driver. */
+       pci_unregister_driver(&mtip_pci_driver);
+}
+
+MODULE_AUTHOR("Micron Technology, Inc");
+MODULE_DESCRIPTION("Micron RealSSD PCIe Block Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MTIP_DRV_VERSION);
+
+module_init(mtip_init);
+module_exit(mtip_exit);
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
new file mode 100644 (file)
index 0000000..723d7c4
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * mtip32xx.h - Header file for the P320 SSD Block Driver
+ *   Copyright (C) 2011 Micron Technology, Inc.
+ *
+ * Portions of this code were derived from works subjected to the
+ * following copyright:
+ *    Copyright (C) 2009 Integrated Device Technology, 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.
+ *
+ */
+
+#ifndef __MTIP32XX_H__
+#define __MTIP32XX_H__
+
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+#include <linux/ata.h>
+#include <linux/interrupt.h>
+#include <linux/genhd.h>
+#include <linux/version.h>
+
+/* Offset of Subsystem Device ID in pci confoguration space */
+#define PCI_SUBSYSTEM_DEVICEID 0x2E
+
+/* offset of Device Control register in PCIe extended capabilites space */
+#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
+
+/* # of times to retry timed out IOs */
+#define MTIP_MAX_RETRIES       5
+
+/* Various timeout values in ms */
+#define MTIP_NCQ_COMMAND_TIMEOUT_MS       5000
+#define MTIP_IOCTL_COMMAND_TIMEOUT_MS     5000
+#define MTIP_INTERNAL_COMMAND_TIMEOUT_MS  5000
+
+/* check for timeouts every 500ms */
+#define MTIP_TIMEOUT_CHECK_PERIOD      500
+
+/* ftl rebuild */
+#define MTIP_FTL_REBUILD_OFFSET                142
+#define MTIP_FTL_REBUILD_MAGIC         0xED51
+#define MTIP_FTL_REBUILD_TIMEOUT_MS    2400000
+
+/* Macro to extract the tag bit number from a tag value. */
+#define MTIP_TAG_BIT(tag)      (tag & 0x1F)
+
+/*
+ * Macro to extract the tag index from a tag value. The index
+ * is used to access the correct s_active/Command Issue register based
+ * on the tag value.
+ */
+#define MTIP_TAG_INDEX(tag)    (tag >> 5)
+
+/*
+ * Maximum number of scatter gather entries
+ * a single command may have.
+ */
+#define MTIP_MAX_SG            128
+
+/*
+ * Maximum number of slot groups (Command Issue & s_active registers)
+ * NOTE: This is the driver maximum; check dd->slot_groups for actual value.
+ */
+#define MTIP_MAX_SLOT_GROUPS   8
+
+/* Internal command tag. */
+#define MTIP_TAG_INTERNAL      0
+
+/* Micron Vendor ID & P320x SSD Device ID */
+#define PCI_VENDOR_ID_MICRON    0x1344
+#define P320_DEVICE_ID         0x5150
+
+/* Driver name and version strings */
+#define MTIP_DRV_NAME          "mtip32xx"
+#define MTIP_DRV_VERSION       "1.2.6os3"
+
+/* Maximum number of minor device numbers per device. */
+#define MTIP_MAX_MINORS                16
+
+/* Maximum number of supported command slots. */
+#define MTIP_MAX_COMMAND_SLOTS (MTIP_MAX_SLOT_GROUPS * 32)
+
+/*
+ * Per-tag bitfield size in longs.
+ * Linux bit manipulation functions
+ * (i.e. test_and_set_bit, find_next_zero_bit)
+ * manipulate memory in longs, so we try to make the math work.
+ * take the slot groups and find the number of longs, rounding up.
+ * Careful! i386 and x86_64 use different size longs!
+ */
+#define U32_PER_LONG   (sizeof(long) / sizeof(u32))
+#define SLOTBITS_IN_LONGS ((MTIP_MAX_SLOT_GROUPS + \
+                                       (U32_PER_LONG-1))/U32_PER_LONG)
+
+/* BAR number used to access the HBA registers. */
+#define MTIP_ABAR              5
+
+/* Forced Unit Access Bit */
+#define FUA_BIT                        0x80
+
+#ifdef DEBUG
+ #define dbg_printk(format, arg...)    \
+       printk(pr_fmt(format), ##arg);
+#else
+ #define dbg_printk(format, arg...)
+#endif
+
+#define __force_bit2int (unsigned int __force)
+
+/* below are bit numbers in 'flags' defined in mtip_port */
+#define MTIP_FLAG_IC_ACTIVE_BIT                        0
+#define MTIP_FLAG_EH_ACTIVE_BIT                        1
+#define MTIP_FLAG_SVC_THD_ACTIVE_BIT           2
+#define MTIP_FLAG_ISSUE_CMDS_BIT               4
+#define MTIP_FLAG_REBUILD_BIT                  5
+#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT      8
+
+/* Register Frame Information Structure (FIS), host to device. */
+struct host_to_dev_fis {
+       /*
+        * FIS type.
+        * - 27h Register FIS, host to device.
+        * - 34h Register FIS, device to host.
+        * - 39h DMA Activate FIS, device to host.
+        * - 41h DMA Setup FIS, bi-directional.
+        * - 46h Data FIS, bi-directional.
+        * - 58h BIST Activate FIS, bi-directional.
+        * - 5Fh PIO Setup FIS, device to host.
+        * - A1h Set Device Bits FIS, device to host.
+        */
+       unsigned char type;
+       unsigned char opts;
+       unsigned char command;
+       unsigned char features;
+
+       union {
+               unsigned char lba_low;
+               unsigned char sector;
+       };
+       union {
+               unsigned char lba_mid;
+               unsigned char cyl_low;
+       };
+       union {
+               unsigned char lba_hi;
+               unsigned char cyl_hi;
+       };
+       union {
+               unsigned char device;
+               unsigned char head;
+       };
+
+       union {
+               unsigned char lba_low_ex;
+               unsigned char sector_ex;
+       };
+       union {
+               unsigned char lba_mid_ex;
+               unsigned char cyl_low_ex;
+       };
+       union {
+               unsigned char lba_hi_ex;
+               unsigned char cyl_hi_ex;
+       };
+       unsigned char features_ex;
+
+       unsigned char sect_count;
+       unsigned char sect_cnt_ex;
+       unsigned char res2;
+       unsigned char control;
+
+       unsigned int res3;
+};
+
+/* Command header structure. */
+struct mtip_cmd_hdr {
+       /*
+        * Command options.
+        * - Bits 31:16 Number of PRD entries.
+        * - Bits 15:8 Unused in this implementation.
+        * - Bit 7 Prefetch bit, informs the drive to prefetch PRD entries.
+        * - Bit 6 Write bit, should be set when writing data to the device.
+        * - Bit 5 Unused in this implementation.
+        * - Bits 4:0 Length of the command FIS in DWords (DWord = 4 bytes).
+        */
+       unsigned int opts;
+       /* This field is unsed when using NCQ. */
+       union {
+               unsigned int byte_count;
+               unsigned int status;
+       };
+       /*
+        * Lower 32 bits of the command table address associated with this
+        * header. The command table addresses must be 128 byte aligned.
+        */
+       unsigned int ctba;
+       /*
+        * If 64 bit addressing is used this field is the upper 32 bits
+        * of the command table address associated with this command.
+        */
+       unsigned int ctbau;
+       /* Reserved and unused. */
+       unsigned int res[4];
+};
+
+/* Command scatter gather structure (PRD). */
+struct mtip_cmd_sg {
+       /*
+        * Low 32 bits of the data buffer address. For P320 this
+        * address must be 8 byte aligned signified by bits 2:0 being
+        * set to 0.
+        */
+       unsigned int dba;
+       /*
+        * When 64 bit addressing is used this field is the upper
+        * 32 bits of the data buffer address.
+        */
+       unsigned int dba_upper;
+       /* Unused. */
+       unsigned int reserved;
+       /*
+        * Bit 31: interrupt when this data block has been transferred.
+        * Bits 30..22: reserved
+        * Bits 21..0: byte count (minus 1).  For P320 the byte count must be
+        * 8 byte aligned signified by bits 2:0 being set to 1.
+        */
+       unsigned int info;
+};
+struct mtip_port;
+
+/* Structure used to describe a command. */
+struct mtip_cmd {
+
+       struct mtip_cmd_hdr *command_header; /* ptr to command header entry */
+
+       dma_addr_t command_header_dma; /* corresponding physical address */
+
+       void *command; /* ptr to command table entry */
+
+       dma_addr_t command_dma; /* corresponding physical address */
+
+       void *comp_data; /* data passed to completion function comp_func() */
+       /*
+        * Completion function called by the ISR upon completion of
+        * a command.
+        */
+       void (*comp_func)(struct mtip_port *port,
+                               int tag,
+                               void *data,
+                               int status);
+       /* Additional callback function that may be called by comp_func() */
+       void (*async_callback)(void *data, int status);
+
+       void *async_data; /* Addl. data passed to async_callback() */
+
+       int scatter_ents; /* Number of scatter list entries used */
+
+       struct scatterlist sg[MTIP_MAX_SG]; /* Scatter list entries */
+
+       int retries; /* The number of retries left for this command. */
+
+       int direction; /* Data transfer direction */
+
+       unsigned long comp_time; /* command completion time, in jiffies */
+
+       atomic_t active; /* declares if this command sent to the drive. */
+};
+
+/* Structure used to describe a port. */
+struct mtip_port {
+       /* Pointer back to the driver data for this port. */
+       struct driver_data *dd;
+       /*
+        * Used to determine if the data pointed to by the
+        * identify field is valid.
+        */
+       unsigned long identify_valid;
+       /* Base address of the memory mapped IO for the port. */
+       void __iomem *mmio;
+       /* Array of pointers to the memory mapped s_active registers. */
+       void __iomem *s_active[MTIP_MAX_SLOT_GROUPS];
+       /* Array of pointers to the memory mapped completed registers. */
+       void __iomem *completed[MTIP_MAX_SLOT_GROUPS];
+       /* Array of pointers to the memory mapped Command Issue registers. */
+       void __iomem *cmd_issue[MTIP_MAX_SLOT_GROUPS];
+       /*
+        * Pointer to the beginning of the command header memory as used
+        * by the driver.
+        */
+       void *command_list;
+       /*
+        * Pointer to the beginning of the command header memory as used
+        * by the DMA.
+        */
+       dma_addr_t command_list_dma;
+       /*
+        * Pointer to the beginning of the RX FIS memory as used
+        * by the driver.
+        */
+       void *rxfis;
+       /*
+        * Pointer to the beginning of the RX FIS memory as used
+        * by the DMA.
+        */
+       dma_addr_t rxfis_dma;
+       /*
+        * Pointer to the beginning of the command table memory as used
+        * by the driver.
+        */
+       void *command_table;
+       /*
+        * Pointer to the beginning of the command table memory as used
+        * by the DMA.
+        */
+       dma_addr_t command_tbl_dma;
+       /*
+        * Pointer to the beginning of the identify data memory as used
+        * by the driver.
+        */
+       u16 *identify;
+       /*
+        * Pointer to the beginning of the identify data memory as used
+        * by the DMA.
+        */
+       dma_addr_t identify_dma;
+       /*
+        * Pointer to the beginning of a sector buffer that is used
+        * by the driver when issuing internal commands.
+        */
+       u16 *sector_buffer;
+       /*
+        * Pointer to the beginning of a sector buffer that is used
+        * by the DMA when the driver issues internal commands.
+        */
+       dma_addr_t sector_buffer_dma;
+       /*
+        * Bit significant, used to determine if a command slot has
+        * been allocated. i.e. the slot is in use.  Bits are cleared
+        * when the command slot and all associated data structures
+        * are no longer needed.
+        */
+       unsigned long allocated[SLOTBITS_IN_LONGS];
+       /*
+        * used to queue commands when an internal command is in progress
+        * or error handling is active
+        */
+       unsigned long cmds_to_issue[SLOTBITS_IN_LONGS];
+       /*
+        * Array of command slots. Structure includes pointers to the
+        * command header and command table, and completion function and data
+        * pointers.
+        */
+       struct mtip_cmd commands[MTIP_MAX_COMMAND_SLOTS];
+       /* Used by mtip_service_thread to wait for an event */
+       wait_queue_head_t svc_wait;
+       /*
+        * indicates the state of the port. Also, helps the service thread
+        * to determine its action on wake up.
+        */
+       unsigned long flags;
+       /*
+        * Timer used to complete commands that have been active for too long.
+        */
+       struct timer_list cmd_timer;
+       /*
+        * Semaphore used to block threads if there are no
+        * command slots available.
+        */
+       struct semaphore cmd_slot;
+       /* Spinlock for working around command-issue bug. */
+       spinlock_t cmd_issue_lock;
+};
+
+/*
+ * Driver private data structure.
+ *
+ * One structure is allocated per probed device.
+ */
+struct driver_data {
+       void __iomem *mmio; /* Base address of the HBA registers. */
+
+       int major; /* Major device number. */
+
+       int instance; /* Instance number. First device probed is 0, ... */
+
+       struct gendisk *disk; /* Pointer to our gendisk structure. */
+
+       struct pci_dev *pdev; /* Pointer to the PCI device structure. */
+
+       struct request_queue *queue; /* Our request queue. */
+
+       struct mtip_port *port; /* Pointer to the port data structure. */
+
+       /* Tasklet used to process the bottom half of the ISR. */
+       struct tasklet_struct tasklet;
+
+       unsigned product_type; /* magic value declaring the product type */
+
+       unsigned slot_groups; /* number of slot groups the product supports */
+
+       atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
+
+       unsigned long index; /* Index to determine the disk name */
+
+       unsigned int ftlrebuildflag; /* FTL rebuild flag */
+
+       atomic_t resumeflag; /* Atomic variable to track suspend/resume */
+
+       atomic_t eh_active; /* Flag for error handling tracking */
+
+       struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
+};
+
+#endif
index 15ec4db194d1bb793e4409dfed54563e4b71b080..0088bf60f3689db6a704c1856c4f94a682d7db44 100644 (file)
@@ -39,9 +39,6 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
-#include <linux/loop.h>
-#include <linux/falloc.h>
-#include <linux/fs.h>
 
 #include <xen/events.h>
 #include <xen/page.h>
@@ -362,7 +359,7 @@ static int xen_blkbk_map(struct blkif_request *req,
 {
        struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        int i;
-       int nseg = req->nr_segments;
+       int nseg = req->u.rw.nr_segments;
        int ret = 0;
 
        /*
@@ -416,30 +413,25 @@ static int xen_blkbk_map(struct blkif_request *req,
        return ret;
 }
 
-static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+static int dispatch_discard_io(struct xen_blkif *blkif,
+                               struct blkif_request *req)
 {
        int err = 0;
        int status = BLKIF_RSP_OKAY;
        struct block_device *bdev = blkif->vbd.bdev;
 
-       if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
-               /* just forward the discard request */
+       blkif->st_ds_req++;
+
+       xen_blkif_get(blkif);
+       if (blkif->blk_backend_type == BLKIF_BACKEND_PHY ||
+           blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+               unsigned long secure = (blkif->vbd.discard_secure &&
+                       (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
+                       BLKDEV_DISCARD_SECURE : 0;
                err = blkdev_issue_discard(bdev,
                                req->u.discard.sector_number,
                                req->u.discard.nr_sectors,
-                               GFP_KERNEL, 0);
-       else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
-               /* punch a hole in the backing file */
-               struct loop_device *lo = bdev->bd_disk->private_data;
-               struct file *file = lo->lo_backing_file;
-
-               if (file->f_op->fallocate)
-                       err = file->f_op->fallocate(file,
-                               FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
-                               req->u.discard.sector_number << 9,
-                               req->u.discard.nr_sectors << 9);
-               else
-                       err = -EOPNOTSUPP;
+                               GFP_KERNEL, secure);
        } else
                err = -EOPNOTSUPP;
 
@@ -449,7 +441,9 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
        } else if (err)
                status = BLKIF_RSP_ERROR;
 
-       make_response(blkif, req->id, req->operation, status);
+       make_response(blkif, req->u.discard.id, req->operation, status);
+       xen_blkif_put(blkif);
+       return err;
 }
 
 static void xen_blk_drain_io(struct xen_blkif *blkif)
@@ -573,8 +567,11 @@ __do_block_io_op(struct xen_blkif *blkif)
 
                /* Apply all sanity checks to /private copy/ of request. */
                barrier();
-
-               if (dispatch_rw_block_io(blkif, &req, pending_req))
+               if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+                       free_req(pending_req);
+                       if (dispatch_discard_io(blkif, &req))
+                               break;
+               } else if (dispatch_rw_block_io(blkif, &req, pending_req))
                        break;
 
                /* Yield point for this unbounded loop. */
@@ -633,10 +630,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                blkif->st_f_req++;
                operation = WRITE_FLUSH;
                break;
-       case BLKIF_OP_DISCARD:
-               blkif->st_ds_req++;
-               operation = REQ_DISCARD;
-               break;
        default:
                operation = 0; /* make gcc happy */
                goto fail_response;
@@ -644,9 +637,9 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
        }
 
        /* Check that the number of segments is sane. */
-       nseg = req->nr_segments;
-       if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
-                               operation != REQ_DISCARD) ||
+       nseg = req->u.rw.nr_segments;
+
+       if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
            unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
                pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
                         nseg);
@@ -654,12 +647,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                goto fail_response;
        }
 
-       preq.dev           = req->handle;
+       preq.dev           = req->u.rw.handle;
        preq.sector_number = req->u.rw.sector_number;
        preq.nr_sects      = 0;
 
        pending_req->blkif     = blkif;
-       pending_req->id        = req->id;
+       pending_req->id        = req->u.rw.id;
        pending_req->operation = req->operation;
        pending_req->status    = BLKIF_RSP_OKAY;
        pending_req->nr_pages  = nseg;
@@ -707,7 +700,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
         * the hypercall to unmap the grants - that is all done in
         * xen_blkbk_unmap.
         */
-       if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
+       if (xen_blkbk_map(req, pending_req, seg))
                goto fail_flush;
 
        /*
@@ -739,23 +732,16 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
 
        /* This will be hit if the operation was a flush or discard. */
        if (!bio) {
-               BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
+               BUG_ON(operation != WRITE_FLUSH);
 
-               if (operation == WRITE_FLUSH) {
-                       bio = bio_alloc(GFP_KERNEL, 0);
-                       if (unlikely(bio == NULL))
-                               goto fail_put_bio;
+               bio = bio_alloc(GFP_KERNEL, 0);
+               if (unlikely(bio == NULL))
+                       goto fail_put_bio;
 
-                       biolist[nbio++] = bio;
-                       bio->bi_bdev    = preq.bdev;
-                       bio->bi_private = pending_req;
-                       bio->bi_end_io  = end_block_io_op;
-               } else if (operation == REQ_DISCARD) {
-                       xen_blk_discard(blkif, req);
-                       xen_blkif_put(blkif);
-                       free_req(pending_req);
-                       return 0;
-               }
+               biolist[nbio++] = bio;
+               bio->bi_bdev    = preq.bdev;
+               bio->bi_private = pending_req;
+               bio->bi_end_io  = end_block_io_op;
        }
 
        /*
@@ -784,7 +770,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
        xen_blkbk_unmap(pending_req);
  fail_response:
        /* Haven't submitted any bio's yet. */
-       make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+       make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR);
        free_req(pending_req);
        msleep(1); /* back off a bit */
        return -EIO;
index dfb1b3a43a5ddc2edbe9310a1ab43af40a71c117..d0ee7edc9be8ad1819a91a491eb907f18d545fbf 100644 (file)
@@ -60,58 +60,66 @@ struct blkif_common_response {
        char dummy;
 };
 
-/* i386 protocol version */
-#pragma pack(push, 4)
-
 struct blkif_x86_32_request_rw {
+       uint8_t        nr_segments;  /* number of segments                   */
+       blkif_vdev_t   handle;       /* only for read/write requests         */
+       uint64_t       id;           /* private guest value, echoed in resp  */
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
        struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
 
 struct blkif_x86_32_request_discard {
+       uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero         */
+       blkif_vdev_t   _pad1;        /* was "handle" for read/write requests */
+       uint64_t       id;           /* private guest value, echoed in resp  */
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-       uint64_t nr_sectors;
-};
+       uint64_t       nr_sectors;
+} __attribute__((__packed__));
 
 struct blkif_x86_32_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
-       uint8_t        nr_segments;  /* number of segments                   */
-       blkif_vdev_t   handle;       /* only for read/write requests         */
-       uint64_t       id;           /* private guest value, echoed in resp  */
        union {
                struct blkif_x86_32_request_rw rw;
                struct blkif_x86_32_request_discard discard;
        } u;
-};
+} __attribute__((__packed__));
+
+/* i386 protocol version */
+#pragma pack(push, 4)
 struct blkif_x86_32_response {
        uint64_t        id;              /* copied from request */
        uint8_t         operation;       /* copied from request */
        int16_t         status;          /* BLKIF_RSP_???       */
 };
 #pragma pack(pop)
-
 /* x86_64 protocol version */
 
 struct blkif_x86_64_request_rw {
+       uint8_t        nr_segments;  /* number of segments                   */
+       blkif_vdev_t   handle;       /* only for read/write requests         */
+       uint32_t       _pad1;        /* offsetof(blkif_reqest..,u.rw.id)==8  */
+       uint64_t       id;
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
        struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
 
 struct blkif_x86_64_request_discard {
+       uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero         */
+       blkif_vdev_t   _pad1;        /* was "handle" for read/write requests */
+        uint32_t       _pad2;        /* offsetof(blkif_..,u.discard.id)==8   */
+       uint64_t       id;
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-       uint64_t nr_sectors;
-};
+       uint64_t       nr_sectors;
+} __attribute__((__packed__));
 
 struct blkif_x86_64_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
-       uint8_t        nr_segments;  /* number of segments                   */
-       blkif_vdev_t   handle;       /* only for read/write requests         */
-       uint64_t       __attribute__((__aligned__(8))) id;
        union {
                struct blkif_x86_64_request_rw rw;
                struct blkif_x86_64_request_discard discard;
        } u;
-};
+} __attribute__((__packed__));
+
 struct blkif_x86_64_response {
        uint64_t       __attribute__((__aligned__(8))) id;
        uint8_t         operation;       /* copied from request */
@@ -156,6 +164,7 @@ struct xen_vbd {
        /* Cached size parameter. */
        sector_t                size;
        bool                    flush_support;
+       bool                    discard_secure;
 };
 
 struct backend_info;
@@ -237,22 +246,23 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
 {
        int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
        dst->operation = src->operation;
-       dst->nr_segments = src->nr_segments;
-       dst->handle = src->handle;
-       dst->id = src->id;
        switch (src->operation) {
        case BLKIF_OP_READ:
        case BLKIF_OP_WRITE:
        case BLKIF_OP_WRITE_BARRIER:
        case BLKIF_OP_FLUSH_DISKCACHE:
+               dst->u.rw.nr_segments = src->u.rw.nr_segments;
+               dst->u.rw.handle = src->u.rw.handle;
+               dst->u.rw.id = src->u.rw.id;
                dst->u.rw.sector_number = src->u.rw.sector_number;
                barrier();
-               if (n > dst->nr_segments)
-                       n = dst->nr_segments;
+               if (n > dst->u.rw.nr_segments)
+                       n = dst->u.rw.nr_segments;
                for (i = 0; i < n; i++)
                        dst->u.rw.seg[i] = src->u.rw.seg[i];
                break;
        case BLKIF_OP_DISCARD:
+               dst->u.discard.flag = src->u.discard.flag;
                dst->u.discard.sector_number = src->u.discard.sector_number;
                dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
                break;
@@ -266,22 +276,23 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
 {
        int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
        dst->operation = src->operation;
-       dst->nr_segments = src->nr_segments;
-       dst->handle = src->handle;
-       dst->id = src->id;
        switch (src->operation) {
        case BLKIF_OP_READ:
        case BLKIF_OP_WRITE:
        case BLKIF_OP_WRITE_BARRIER:
        case BLKIF_OP_FLUSH_DISKCACHE:
+               dst->u.rw.nr_segments = src->u.rw.nr_segments;
+               dst->u.rw.handle = src->u.rw.handle;
+               dst->u.rw.id = src->u.rw.id;
                dst->u.rw.sector_number = src->u.rw.sector_number;
                barrier();
-               if (n > dst->nr_segments)
-                       n = dst->nr_segments;
+               if (n > dst->u.rw.nr_segments)
+                       n = dst->u.rw.nr_segments;
                for (i = 0; i < n; i++)
                        dst->u.rw.seg[i] = src->u.rw.seg[i];
                break;
        case BLKIF_OP_DISCARD:
+               dst->u.discard.flag = src->u.discard.flag;
                dst->u.discard.sector_number = src->u.discard.sector_number;
                dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
                break;
index 37c794d312644d30430446d32e3ed844565cc362..24a2fb57e5d012d57c5d3e1fc1929f27ac3998ee 100644 (file)
@@ -338,6 +338,9 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
        if (q && q->flush_flags)
                vbd->flush_support = true;
 
+       if (q && blk_queue_secdiscard(q))
+               vbd->discard_secure = true;
+
        DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
                handle, blkif->domid);
        return 0;
@@ -420,6 +423,15 @@ int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
                                state = 1;
                                blkif->blk_backend_type = BLKIF_BACKEND_PHY;
                        }
+                       /* Optional. */
+                       err = xenbus_printf(xbt, dev->nodename,
+                               "discard-secure", "%d",
+                               blkif->vbd.discard_secure);
+                       if (err) {
+                               xenbus_dev_fatal(dev, err,
+                                       "writting discard-secure");
+                               goto kfree;
+                       }
                }
        } else {
                err = PTR_ERR(type);
index 9fd3ee203b1e7b5e450c3e32737e61a64f9cc6b1..2f22874c0a374df53ef5f264b42901ac3fc15979 100644 (file)
@@ -98,7 +98,8 @@ struct blkfront_info
        unsigned long shadow_free;
        unsigned int feature_flush;
        unsigned int flush_op;
-       unsigned int feature_discard;
+       unsigned int feature_discard:1;
+       unsigned int feature_secdiscard:1;
        unsigned int discard_granularity;
        unsigned int discard_alignment;
        int is_ready;
@@ -135,15 +136,15 @@ static int get_id_from_freelist(struct blkfront_info *info)
 {
        unsigned long free = info->shadow_free;
        BUG_ON(free >= BLK_RING_SIZE);
-       info->shadow_free = info->shadow[free].req.id;
-       info->shadow[free].req.id = 0x0fffffee; /* debug */
+       info->shadow_free = info->shadow[free].req.u.rw.id;
+       info->shadow[free].req.u.rw.id = 0x0fffffee; /* debug */
        return free;
 }
 
 static void add_id_to_freelist(struct blkfront_info *info,
                               unsigned long id)
 {
-       info->shadow[id].req.id  = info->shadow_free;
+       info->shadow[id].req.u.rw.id  = info->shadow_free;
        info->shadow[id].request = NULL;
        info->shadow_free = id;
 }
@@ -156,7 +157,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr)
        if (end > nr_minors) {
                unsigned long *bitmap, *old;
 
-               bitmap = kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap),
+               bitmap = kcalloc(BITS_TO_LONGS(end), sizeof(*bitmap),
                                 GFP_KERNEL);
                if (bitmap == NULL)
                        return -ENOMEM;
@@ -287,9 +288,9 @@ static int blkif_queue_request(struct request *req)
        id = get_id_from_freelist(info);
        info->shadow[id].request = req;
 
-       ring_req->id = id;
+       ring_req->u.rw.id = id;
        ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
-       ring_req->handle = info->handle;
+       ring_req->u.rw.handle = info->handle;
 
        ring_req->operation = rq_data_dir(req) ?
                BLKIF_OP_WRITE : BLKIF_OP_READ;
@@ -305,16 +306,21 @@ static int blkif_queue_request(struct request *req)
                ring_req->operation = info->flush_op;
        }
 
-       if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+       if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) {
                /* id, sector_number and handle are set above. */
                ring_req->operation = BLKIF_OP_DISCARD;
-               ring_req->nr_segments = 0;
                ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+               if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
+                       ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
+               else
+                       ring_req->u.discard.flag = 0;
        } else {
-               ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
-               BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+               ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req,
+                                                          info->sg);
+               BUG_ON(ring_req->u.rw.nr_segments >
+                      BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-               for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+               for_each_sg(info->sg, sg, ring_req->u.rw.nr_segments, i) {
                        buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
                        fsect = sg->offset >> 9;
                        lsect = fsect + (sg->length >> 9) - 1;
@@ -424,6 +430,8 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
                blk_queue_max_discard_sectors(rq, get_capacity(gd));
                rq->limits.discard_granularity = info->discard_granularity;
                rq->limits.discard_alignment = info->discard_alignment;
+               if (info->feature_secdiscard)
+                       queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, rq);
        }
 
        /* Hard sector size and max sectors impersonate the equiv. hardware. */
@@ -705,7 +713,9 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 static void blkif_completion(struct blk_shadow *s)
 {
        int i;
-       for (i = 0; i < s->req.nr_segments; i++)
+       /* Do not let BLKIF_OP_DISCARD as nr_segment is in the same place
+        * flag. */
+       for (i = 0; i < s->req.u.rw.nr_segments; i++)
                gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
 }
 
@@ -736,7 +746,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                id   = bret->id;
                req  = info->shadow[id].request;
 
-               blkif_completion(&info->shadow[id]);
+               if (bret->operation != BLKIF_OP_DISCARD)
+                       blkif_completion(&info->shadow[id]);
 
                add_id_to_freelist(info, id);
 
@@ -749,7 +760,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                                           info->gd->disk_name);
                                error = -EOPNOTSUPP;
                                info->feature_discard = 0;
+                               info->feature_secdiscard = 0;
                                queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+                               queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq);
                        }
                        __blk_end_request_all(req, error);
                        break;
@@ -763,7 +776,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                                error = -EOPNOTSUPP;
                        }
                        if (unlikely(bret->status == BLKIF_RSP_ERROR &&
-                                    info->shadow[id].req.nr_segments == 0)) {
+                                    info->shadow[id].req.u.rw.nr_segments == 0)) {
                                printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n",
                                       info->flush_op == BLKIF_OP_WRITE_BARRIER ?
                                       "barrier" :  "flush disk cache",
@@ -984,8 +997,8 @@ static int blkfront_probe(struct xenbus_device *dev,
        INIT_WORK(&info->work, blkif_restart_queue);
 
        for (i = 0; i < BLK_RING_SIZE; i++)
-               info->shadow[i].req.id = i+1;
-       info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+               info->shadow[i].req.u.rw.id = i+1;
+       info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff;
 
        /* Front end dir is a number, which is used as the id. */
        info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0);
@@ -1019,9 +1032,9 @@ static int blkif_recover(struct blkfront_info *info)
        /* Stage 2: Set up free list. */
        memset(&info->shadow, 0, sizeof(info->shadow));
        for (i = 0; i < BLK_RING_SIZE; i++)
-               info->shadow[i].req.id = i+1;
+               info->shadow[i].req.u.rw.id = i+1;
        info->shadow_free = info->ring.req_prod_pvt;
-       info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+       info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff;
 
        /* Stage 3: Find pending requests and requeue them. */
        for (i = 0; i < BLK_RING_SIZE; i++) {
@@ -1034,17 +1047,19 @@ static int blkif_recover(struct blkfront_info *info)
                *req = copy[i].req;
 
                /* We get a new request id, and must reset the shadow state. */
-               req->id = get_id_from_freelist(info);
-               memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
+               req->u.rw.id = get_id_from_freelist(info);
+               memcpy(&info->shadow[req->u.rw.id], &copy[i], sizeof(copy[i]));
 
+               if (req->operation != BLKIF_OP_DISCARD) {
                /* Rewrite any grant references invalidated by susp/resume. */
-               for (j = 0; j < req->nr_segments; j++)
-                       gnttab_grant_foreign_access_ref(
-                               req->u.rw.seg[j].gref,
-                               info->xbdev->otherend_id,
-                               pfn_to_mfn(info->shadow[req->id].frame[j]),
-                               rq_data_dir(info->shadow[req->id].request));
-               info->shadow[req->id].req = *req;
+                       for (j = 0; j < req->u.rw.nr_segments; j++)
+                               gnttab_grant_foreign_access_ref(
+                                       req->u.rw.seg[j].gref,
+                                       info->xbdev->otherend_id,
+                                       pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]),
+                                       rq_data_dir(info->shadow[req->u.rw.id].request));
+               }
+               info->shadow[req->u.rw.id].req = *req;
 
                info->ring.req_prod_pvt++;
        }
@@ -1135,11 +1150,13 @@ static void blkfront_setup_discard(struct blkfront_info *info)
        char *type;
        unsigned int discard_granularity;
        unsigned int discard_alignment;
+       unsigned int discard_secure;
 
        type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
        if (IS_ERR(type))
                return;
 
+       info->feature_secdiscard = 0;
        if (strncmp(type, "phy", 3) == 0) {
                err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
                        "discard-granularity", "%u", &discard_granularity,
@@ -1150,6 +1167,12 @@ static void blkfront_setup_discard(struct blkfront_info *info)
                        info->discard_granularity = discard_granularity;
                        info->discard_alignment = discard_alignment;
                }
+               err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                           "discard-secure", "%d", &discard_secure,
+                           NULL);
+               if (!err)
+                       info->feature_secdiscard = discard_secure;
+
        } else if (strncmp(type, "file", 4) == 0)
                info->feature_discard = 1;
 
index 732215b805c1af45f391769702c0b515ea888cb1..54ca8b23cde3f1aa5550d2806087300227531070 100644 (file)
@@ -965,6 +965,7 @@ EXPORT_SYMBOL(get_random_bytes);
  */
 static void init_std_data(struct entropy_store *r)
 {
+       int i;
        ktime_t now;
        unsigned long flags;
 
@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r)
 
        now = ktime_get_real();
        mix_pool_bytes(r, &now, sizeof(now));
+       for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
+               if (!arch_get_random_long(&flags))
+                       break;
+               mix_pool_bytes(r, &flags, sizeof(flags));
+       }
        mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
 }
 
index cb351d3583875a8ea1ebbb78ae681cb888e5dee3..02260406b9e440ac406ac3ae7fc3cded1f05bb4e 100644 (file)
@@ -474,8 +474,8 @@ config SENSORS_IT87
        select HWMON_VID
        help
          If you say yes here you get support for ITE IT8705F, IT8712F,
-         IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor
-         chips, and the SiS960 clone.
+         IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
+         sensor chips, and the SiS960 clone.
 
          This driver can also be built as a module.  If so, the module
          will be called it87.
@@ -515,11 +515,11 @@ config SENSORS_LINEAGE
          will be called lineage-pem.
 
 config SENSORS_LM63
-       tristate "National Semiconductor LM63 and LM64"
+       tristate "National Semiconductor LM63 and compatibles"
        depends on I2C
        help
          If you say yes here you get support for the National
-         Semiconductor LM63 and LM64 remote diode digital temperature
+         Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
          sensors with integrated fan control.  Such chips are found
          on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
          others.
index e6291dafa4caab89a36feb2cdc1a50abde70364c..97e2cfb0bc9365827bac1d40667954d18e4d0fc1 100644 (file)
@@ -155,7 +155,8 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
 #define TEMP_OFFSET_FROM_REG(val)      TEMP_FROM_REG((val) < 0 ? \
                                                      (val) | 0x70 : (val))
 
-#define FAN_FROM_REG(reg, div)         ((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
+#define FAN_FROM_REG(reg, div)         ((reg) ? \
+                                        (11250 * 60) / ((reg) * (div)) : 0)
 
 static int FAN_TO_REG(int reg, int div)
 {
@@ -174,8 +175,8 @@ static int FAN_TO_REG(int reg, int div)
        (((reg) & 0x1F) | (((val) << 5) & 0xe0))
 
 #define AUTO_TEMP_MIN_TO_REG(val, reg) \
-       ((((val)/500) & 0xf8)|((reg) & 0x7))
-#define AUTO_TEMP_RANGE_FROM_REG(reg)  (5000 * (1<< ((reg)&0x7)))
+       ((((val) / 500) & 0xf8) | ((reg) & 0x7))
+#define AUTO_TEMP_RANGE_FROM_REG(reg)  (5000 * (1 << ((reg) & 0x7)))
 #define AUTO_TEMP_MIN_FROM_REG(reg)    (1000 * ((((reg) >> 3) & 0x1f) << 2))
 
 #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)        ((((reg) >> 3) & 0x1f) << 2)
@@ -202,7 +203,7 @@ static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
 
 /* FAN auto control */
 #define GET_FAN_AUTO_BITFIELD(data, idx)       \
-       (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
+       (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
 
 /* The tables below contains the possible values for the auto fan
  * control bitfields. the index in the table is the register value.
@@ -230,7 +231,7 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = {
  */
 static int
 get_fan_auto_nearest(struct adm1031_data *data,
-                    int chan, u8 val, u8 reg, u8 * new_reg)
+                    int chan, u8 val, u8 reg, u8 *new_reg)
 {
        int i;
        int first_match = -1, exact_match = -1;
@@ -258,13 +259,13 @@ get_fan_auto_nearest(struct adm1031_data *data,
                }
        }
 
-       if (exact_match >= 0) {
+       if (exact_match >= 0)
                *new_reg = exact_match;
-       } else if (first_match >= 0) {
+       else if (first_match >= 0)
                *new_reg = first_match;
-       } else {
+       else
                return -EINVAL;
-       }
+
        return 0;
 }
 
@@ -283,23 +284,28 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
+       long val;
        u8 reg;
        int ret;
        u8 old_fan_mode;
 
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
        old_fan_mode = data->conf1;
 
        mutex_lock(&data->update_lock);
 
-       if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
+       ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg);
+       if (ret) {
                mutex_unlock(&data->update_lock);
                return ret;
        }
        data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
        if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
            (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
-               if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
+               if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
                        /* Switch to Auto Fan Mode
                         * Save PWM registers
                         * Set PWM registers to 33% Both */
@@ -350,7 +356,12 @@ set_auto_temp_min(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
        mutex_lock(&data->update_lock);
        data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
@@ -374,10 +385,16 @@ set_auto_temp_max(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
        mutex_lock(&data->update_lock);
-       data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
+       data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
+                                                 data->pwm[nr]);
        adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
                            data->temp_max[nr]);
        mutex_unlock(&data->update_lock);
@@ -410,8 +427,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
-       int reg;
+       long val;
+       int ret, reg;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
        mutex_lock(&data->update_lock);
        if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
@@ -449,9 +470,13 @@ static int trust_fan_readings(struct adm1031_data *data, int chan)
 
        if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
                switch (data->conf1 & 0x60) {
-               case 0x00:      /* remote temp1 controls fan1 remote temp2 controls fan2 */
+               case 0x00:
+                       /*
+                        * remote temp1 controls fan1,
+                        * remote temp2 controls fan2
+                        */
                        res = data->temp[chan+1] >=
-                             AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
+                           AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
                        break;
                case 0x20:      /* remote temp1 controls both fans */
                        res =
@@ -515,7 +540,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
        mutex_lock(&data->update_lock);
        if (val) {
@@ -534,10 +564,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val = simple_strtol(buf, NULL, 10);
+       long val;
        u8 tmp;
        int old_div;
        int new_min;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
        tmp = val == 8 ? 0xc0 :
              val == 4 ? 0x80 :
@@ -631,9 +666,13 @@ static ssize_t set_temp_offset(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val;
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
-       val = simple_strtol(buf, NULL, 10);
        val = SENSORS_LIMIT(val, -15000, 15000);
        mutex_lock(&data->update_lock);
        data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
@@ -648,9 +687,13 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val;
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
-       val = simple_strtol(buf, NULL, 10);
        val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
        mutex_lock(&data->update_lock);
        data->temp_min[nr] = TEMP_TO_REG(val);
@@ -665,9 +708,13 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val;
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
-       val = simple_strtol(buf, NULL, 10);
        val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
        mutex_lock(&data->update_lock);
        data->temp_max[nr] = TEMP_TO_REG(val);
@@ -682,9 +729,13 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1031_data *data = i2c_get_clientdata(client);
        int nr = to_sensor_dev_attr(attr)->index;
-       int val;
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
 
-       val = simple_strtol(buf, NULL, 10);
        val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
        mutex_lock(&data->update_lock);
        data->temp_crit[nr] = TEMP_TO_REG(val);
@@ -711,7 +762,8 @@ temp_reg(2);
 temp_reg(3);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+                          char *buf)
 {
        struct adm1031_data *data = adm1031_update_device(dev);
        return sprintf(buf, "%d\n", data->alarm);
@@ -919,12 +971,13 @@ static int adm1031_probe(struct i2c_client *client,
        adm1031_init_client(client);
 
        /* Register sysfs hooks */
-       if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
+       err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
+       if (err)
                goto exit_free;
 
        if (data->chip_type == adm1031) {
-               if ((err = sysfs_create_group(&client->dev.kobj,
-                                               &adm1031_group_opt)))
+               err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
+               if (err)
                        goto exit_remove;
        }
 
@@ -970,14 +1023,13 @@ static void adm1031_init_client(struct i2c_client *client)
        }
        /* Initialize the ADM1031 chip (enables fan speed reading ) */
        read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
-       if ((read_val | mask) != read_val) {
-           adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
-       }
+       if ((read_val | mask) != read_val)
+               adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
 
        read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
        if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
-           adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
-                               ADM1031_CONF1_MONITOR_ENABLE);
+               adm1031_write_value(client, ADM1031_REG_CONF1,
+                                   read_val | ADM1031_CONF1_MONITOR_ENABLE);
        }
 
        /* Read the chip's update rate */
@@ -1024,8 +1076,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
                                /* oldh is actually newer */
                                if (newh != oldh)
                                        dev_warn(&client->dev,
-                                                "Remote temperature may be "
-                                                "wrong.\n");
+                                         "Remote temperature may be wrong.\n");
 #endif
                        }
                        data->temp[chan] = newh;
@@ -1052,22 +1103,24 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
                data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
 
                data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
-                            | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
-                               << 8);
-               if (data->chip_type == adm1030) {
+                   | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
+               if (data->chip_type == adm1030)
                        data->alarm &= 0xc0ff;
-               }
 
-               for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
+               for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
+                    chan++) {
                        data->fan_div[chan] =
-                           adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
+                           adm1031_read_value(client,
+                                              ADM1031_REG_FAN_DIV(chan));
                        data->fan_min[chan] =
-                           adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
+                           adm1031_read_value(client,
+                                              ADM1031_REG_FAN_MIN(chan));
                        data->fan[chan] =
-                           adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
+                           adm1031_read_value(client,
+                                              ADM1031_REG_FAN_SPEED(chan));
                        data->pwm[chan] =
-                           0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
-                                  (4*chan));
+                         (adm1031_read_value(client,
+                                       ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
                }
                data->last_updated = jiffies;
                data->valid = 1;
index 1fdef885341c4438842c92a381726e864dd3868c..a6c6ec36615e686b296fd4b199107eae08f2ba34 100644 (file)
@@ -190,7 +190,8 @@ static ssize_t show_temp(struct device *dev,
        return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
 }
 
-static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
+static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
+                                 struct device *dev)
 {
        /* The 100C is default for both mobile and non mobile CPUs */
 
@@ -284,7 +285,8 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
        return tjmax;
 }
 
-static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
+static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
+                              struct device *dev)
 {
        int err;
        u32 eax, edx;
@@ -323,7 +325,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
        return adjust_tjmax(c, id, dev);
 }
 
-static int create_name_attr(struct platform_data *pdata, struct device *dev)
+static int __devinit create_name_attr(struct platform_data *pdata,
+                                     struct device *dev)
 {
        sysfs_attr_init(&pdata->name_attr.attr);
        pdata->name_attr.attr.name = "name";
@@ -332,8 +335,8 @@ static int create_name_attr(struct platform_data *pdata, struct device *dev)
        return device_create_file(dev, &pdata->name_attr);
 }
 
-static int create_core_attrs(struct temp_data *tdata, struct device *dev,
-                               int attr_no)
+static int __cpuinit create_core_attrs(struct temp_data *tdata,
+                                      struct device *dev, int attr_no)
 {
        int err, i;
        static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
@@ -383,7 +386,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu)
        return 0;
 }
 
-static struct platform_device *coretemp_get_pdev(unsigned int cpu)
+static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu)
 {
        u16 phys_proc_id = TO_PHYS_ID(cpu);
        struct pdev_entry *p;
@@ -400,7 +403,8 @@ static struct platform_device *coretemp_get_pdev(unsigned int cpu)
        return NULL;
 }
 
-static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
+static struct temp_data __cpuinit *init_temp_data(unsigned int cpu,
+                                                 int pkg_flag)
 {
        struct temp_data *tdata;
 
@@ -418,7 +422,7 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
        return tdata;
 }
 
-static int create_core_data(struct platform_device *pdev,
+static int __cpuinit create_core_data(struct platform_device *pdev,
                                unsigned int cpu, int pkg_flag)
 {
        struct temp_data *tdata;
@@ -489,7 +493,7 @@ exit_free:
        return err;
 }
 
-static void coretemp_add_core(unsigned int cpu, int pkg_flag)
+static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag)
 {
        struct platform_device *pdev = coretemp_get_pdev(cpu);
        int err;
@@ -618,7 +622,7 @@ exit:
        return err;
 }
 
-static void coretemp_device_remove(unsigned int cpu)
+static void __cpuinit coretemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p, *n;
        u16 phys_proc_id = TO_PHYS_ID(cpu);
@@ -634,7 +638,7 @@ static void coretemp_device_remove(unsigned int cpu)
        mutex_unlock(&pdev_list_mutex);
 }
 
-static bool is_any_core_online(struct platform_data *pdata)
+static bool __cpuinit is_any_core_online(struct platform_data *pdata)
 {
        int i;
 
index 603ef2af270758fb4fd9a6f860a779de40c4288f..0054d6f9cec95e4645608c7fec6fde4f646344ac 100644 (file)
@@ -17,6 +17,7 @@
  *            IT8720F  Super I/O chip w/LPC interface
  *            IT8721F  Super I/O chip w/LPC interface
  *            IT8726F  Super I/O chip w/LPC interface
+ *            IT8728F  Super I/O chip w/LPC interface
  *            IT8758E  Super I/O chip w/LPC interface
  *            Sis950   A clone of the IT8705F
  *
@@ -58,7 +59,7 @@
 
 #define DRVNAME "it87"
 
-enum chips { it87, it8712, it8716, it8718, it8720, it8721 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -135,6 +136,7 @@ static inline void superio_exit(void)
 #define IT8720F_DEVID 0x8720
 #define IT8721F_DEVID 0x8721
 #define IT8726F_DEVID 0x8726
+#define IT8728F_DEVID 0x8728
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -274,11 +276,31 @@ struct it87_data {
        s8 auto_temp[3][5];     /* [nr][0] is point1_temp_hyst */
 };
 
+static inline int has_12mv_adc(const struct it87_data *data)
+{
+       /*
+        * IT8721F and later have a 12 mV ADC, also with internal scaling
+        * on selected inputs.
+        */
+       return data->type == it8721
+           || data->type == it8728;
+}
+
+static inline int has_newer_autopwm(const struct it87_data *data)
+{
+       /*
+        * IT8721F and later have separate registers for the temperature
+        * mapping and the manual duty cycle.
+        */
+       return data->type == it8721
+           || data->type == it8728;
+}
+
 static u8 in_to_reg(const struct it87_data *data, int nr, long val)
 {
        long lsb;
 
-       if (data->type == it8721) {
+       if (has_12mv_adc(data)) {
                if (data->in_scaled & (1 << nr))
                        lsb = 24;
                else
@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val)
 
 static int in_from_reg(const struct it87_data *data, int nr, int val)
 {
-       if (data->type == it8721) {
+       if (has_12mv_adc(data)) {
                if (data->in_scaled & (1 << nr))
                        return val * 24;
                else
@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm)
 
 static u8 pwm_to_reg(const struct it87_data *data, long val)
 {
-       if (data->type == it8721)
+       if (has_newer_autopwm(data))
                return val;
        else
                return val >> 1;
@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val)
 
 static int pwm_from_reg(const struct it87_data *data, u8 reg)
 {
-       if (data->type == it8721)
+       if (has_newer_autopwm(data))
                return reg;
        else
                return (reg & 0x7f) << 1;
@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data)
            || data->type == it8716
            || data->type == it8718
            || data->type == it8720
-           || data->type == it8721;
+           || data->type == it8721
+           || data->type == it8728;
 }
 
 static inline int has_old_autopwm(const struct it87_data *data)
@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev,
                                 data->fan_main_ctrl);
        } else {
                if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = data->type == it8721 ?
+                       data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
                                             data->pwm_temp_map[nr] :
                                             data->pwm_duty[nr];
                else                                    /* Automatic mode */
@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       if (data->type == it8721) {
+       if (has_newer_autopwm(data)) {
                /* If we are in automatic mode, the PWM duty cycle register
                 * is read-only so we can't write the value */
                if (data->pwm_ctrl[nr] & 0x80) {
@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
        struct it87_data *data = dev_get_drvdata(dev);
        int nr = to_sensor_dev_attr(attr)->index;
 
-       return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr]
-                                                        : labels[nr]);
+       return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
+                                                      : labels[nr]);
 }
 static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
 static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address,
        case IT8721F_DEVID:
                sio_data->type = it8721;
                break;
+       case IT8728F_DEVID:
+               sio_data->type = it8728;
+               break;
        case 0xffff:    /* No device at all */
                goto exit;
        default:
@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address,
                superio_select(GPIO);
 
                reg = superio_inb(IT87_SIO_GPIO3_REG);
-               if (sio_data->type == it8721) {
-                       /* The IT8721F/IT8758E doesn't have VID pins at all */
+               if (sio_data->type == it8721 || sio_data->type == it8728) {
+                       /*
+                        * The IT8721F/IT8758E doesn't have VID pins at all,
+                        * not sure about the IT8728F.
+                        */
                        sio_data->skip_vid = 1;
                } else {
                        /* We need at least 4 VID pins */
@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address,
                }
                if (reg & (1 << 0))
                        sio_data->internal |= (1 << 0);
-               if ((reg & (1 << 1)) || sio_data->type == it8721)
+               if ((reg & (1 << 1)) || sio_data->type == it8721 ||
+                   sio_data->type == it8728)
                        sio_data->internal |= (1 << 1);
 
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
                "it8718",
                "it8720",
                "it8721",
+               "it8728",
        };
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
        enable_pwm_interface = it87_check_pwm(dev);
 
        /* Starting with IT8721F, we handle scaling of internal voltages */
-       if (data->type == it8721) {
+       if (has_12mv_adc(data)) {
                if (sio_data->internal & (1 << 0))
                        data->in_scaled |= (1 << 3);    /* in3 is AVCC */
                if (sio_data->internal & (1 << 1))
@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
        data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-       if (data->type == it8721) {
+       if (has_newer_autopwm(data)) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
                data->pwm_duty[nr] = it87_read_value(data,
                                                     IT87_REG_PWM_DUTY(nr));
index 508cb291f71bfc35681bfda50dbad88a1a8a8dc2..5e6457a6644d879ab94830edd6881e0826f6678c 100644 (file)
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/types.h>
 
 /*
  * Addresses to scan
- * Address is fully defined internally and cannot be changed.
+ * Address is fully defined internally and cannot be changed except for
+ * LM64 which has one pin dedicated to address selection.
+ * LM63 and LM96163 have address 0x4c.
+ * LM64 can have address 0x18 or 0x4e.
  */
 
 static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
@@ -60,6 +64,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
  */
 
 #define LM63_REG_CONFIG1               0x03
+#define LM63_REG_CONVRATE              0x04
 #define LM63_REG_CONFIG2               0xBF
 #define LM63_REG_CONFIG_FAN            0x4A
 
@@ -70,6 +75,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
 
 #define LM63_REG_PWM_VALUE             0x4C
 #define LM63_REG_PWM_FREQ              0x4D
+#define LM63_REG_LUT_TEMP_HYST         0x4F
+#define LM63_REG_LUT_TEMP(nr)          (0x50 + 2 * (nr))
+#define LM63_REG_LUT_PWM(nr)           (0x51 + 2 * (nr))
 
 #define LM63_REG_LOCAL_TEMP            0x00
 #define LM63_REG_LOCAL_HIGH            0x05
@@ -91,6 +99,16 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
 #define LM63_REG_MAN_ID                        0xFE
 #define LM63_REG_CHIP_ID               0xFF
 
+#define LM96163_REG_TRUTHERM           0x30
+#define LM96163_REG_REMOTE_TEMP_U_MSB  0x31
+#define LM96163_REG_REMOTE_TEMP_U_LSB  0x32
+#define LM96163_REG_CONFIG_ENHANCED    0x45
+
+#define LM63_MAX_CONVRATE              9
+
+#define LM63_MAX_CONVRATE_HZ           32
+#define LM96163_MAX_CONVRATE_HZ                26
+
 /*
  * Conversions and various macros
  * For tachometer counts, the LM63 uses 16-bit values.
@@ -112,15 +130,24 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
                                 (val) >= 127000 ? 127 : \
                                 (val) < 0 ? ((val) - 500) / 1000 : \
                                 ((val) + 500) / 1000)
+#define TEMP8U_TO_REG(val)     ((val) <= 0 ? 0 : \
+                                (val) >= 255000 ? 255 : \
+                                ((val) + 500) / 1000)
 #define TEMP11_FROM_REG(reg)   ((reg) / 32 * 125)
 #define TEMP11_TO_REG(val)     ((val) <= -128000 ? 0x8000 : \
                                 (val) >= 127875 ? 0x7FE0 : \
                                 (val) < 0 ? ((val) - 62) / 125 * 32 : \
                                 ((val) + 62) / 125 * 32)
+#define TEMP11U_TO_REG(val)    ((val) <= 0 ? 0 : \
+                                (val) >= 255875 ? 0xFFE0 : \
+                                ((val) + 62) / 125 * 32)
 #define HYST_TO_REG(val)       ((val) <= 0 ? 0 : \
                                 (val) >= 127000 ? 127 : \
                                 ((val) + 500) / 1000)
 
+#define UPDATE_INTERVAL(max, rate) \
+                       ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
+
 /*
  * Functions declaration
  */
@@ -134,7 +161,7 @@ static struct lm63_data *lm63_update_device(struct device *dev);
 static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
 static void lm63_init_client(struct i2c_client *client);
 
-enum chips { lm63, lm64 };
+enum chips { lm63, lm64, lm96163 };
 
 /*
  * Driver data (common to all clients)
@@ -143,6 +170,7 @@ enum chips { lm63, lm64 };
 static const struct i2c_device_id lm63_id[] = {
        { "lm63", lm63 },
        { "lm64", lm64 },
+       { "lm96163", lm96163 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm63_id);
@@ -167,26 +195,53 @@ struct lm63_data {
        struct device *hwmon_dev;
        struct mutex update_lock;
        char valid; /* zero until following fields are valid */
+       char lut_valid; /* zero until lut fields are valid */
        unsigned long last_updated; /* in jiffies */
-       int kind;
+       unsigned long lut_last_updated; /* in jiffies */
+       enum chips kind;
        int temp2_offset;
 
+       int update_interval;    /* in milliseconds */
+       int max_convrate_hz;
+       int lut_size;           /* 8 or 12 */
+
        /* registers values */
        u8 config, config_fan;
        u16 fan[2];     /* 0: input
                           1: low limit */
        u8 pwm1_freq;
-       u8 pwm1_value;
-       s8 temp8[3];    /* 0: local input
+       u8 pwm1[13];    /* 0: current output
+                          1-12: lookup table */
+       s8 temp8[15];   /* 0: local input
                           1: local high limit
-                          2: remote critical limit */
-       s16 temp11[3];  /* 0: remote input
+                          2: remote critical limit
+                          3-14: lookup table */
+       s16 temp11[4];  /* 0: remote input
                           1: remote low limit
-                          2: remote high limit */
+                          2: remote high limit
+                          3: remote offset */
+       u16 temp11u;    /* remote input (unsigned) */
        u8 temp2_crit_hyst;
+       u8 lut_temp_hyst;
        u8 alarms;
+       bool pwm_highres;
+       bool lut_temp_highres;
+       bool remote_unsigned; /* true if unsigned remote upper limits */
+       bool trutherm;
 };
 
+static inline int temp8_from_reg(struct lm63_data *data, int nr)
+{
+       if (data->remote_unsigned)
+               return TEMP8_FROM_REG((u8)data->temp8[nr]);
+       return TEMP8_FROM_REG(data->temp8[nr]);
+}
+
+static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
+{
+       return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
+}
+
 /*
  * Sysfs callback functions and files
  */
@@ -204,7 +259,12 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
-       unsigned long val = simple_strtoul(buf, NULL, 10);
+       unsigned long val;
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err)
+               return err;
 
        mutex_lock(&data->update_lock);
        data->fan[1] = FAN_TO_REG(val);
@@ -216,13 +276,22 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
        return count;
 }
 
-static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
                         char *buf)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct lm63_data *data = lm63_update_device(dev);
-       return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
-                      255 : (data->pwm1_value * 255 + data->pwm1_freq) /
-                      (2 * data->pwm1_freq));
+       int nr = attr->index;
+       int pwm;
+
+       if (data->pwm_highres)
+               pwm = data->pwm1[nr];
+       else
+               pwm = data->pwm1[nr] >= 2 * data->pwm1_freq ?
+                      255 : (data->pwm1[nr] * 255 + data->pwm1_freq) /
+                      (2 * data->pwm1_freq);
+
+       return sprintf(buf, "%d\n", pwm);
 }
 
 static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
@@ -231,22 +300,26 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
        unsigned long val;
-       
+       int err;
+
        if (!(data->config_fan & 0x20)) /* register is read-only */
                return -EPERM;
 
-       val = simple_strtoul(buf, NULL, 10);
+       err = kstrtoul(buf, 10, &val);
+       if (err)
+               return err;
+
+       val = SENSORS_LIMIT(val, 0, 255);
        mutex_lock(&data->update_lock);
-       data->pwm1_value = val <= 0 ? 0 :
-                          val >= 255 ? 2 * data->pwm1_freq :
-                          (val * data->pwm1_freq * 2 + 127) / 255;
-       i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value);
+       data->pwm1[0] = data->pwm_highres ? val :
+                       (val * data->pwm1_freq * 2 + 127) / 255;
+       i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
-                               char *buf)
+static ssize_t show_pwm1_enable(struct device *dev,
+                               struct device_attribute *dummy, char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
        return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
@@ -273,21 +346,47 @@ static ssize_t show_remote_temp8(struct device *dev,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct lm63_data *data = lm63_update_device(dev);
-       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])
+       return sprintf(buf, "%d\n", temp8_from_reg(data, attr->index)
+                      + data->temp2_offset);
+}
+
+static ssize_t show_lut_temp(struct device *dev,
+                             struct device_attribute *devattr,
+                             char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+       return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
                       + data->temp2_offset);
 }
 
-static ssize_t set_local_temp8(struct device *dev,
-                              struct device_attribute *dummy,
-                              const char *buf, size_t count)
+static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
+                        const char *buf, size_t count)
 {
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
-       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+       int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
+       long val;
+       int err;
+       int temp;
+
+       err = kstrtol(buf, 10, &val);
+       if (err)
+               return err;
 
        mutex_lock(&data->update_lock);
-       data->temp8[1] = TEMP8_TO_REG(val);
-       i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
+       if (nr == 2) {
+               if (data->remote_unsigned)
+                       temp = TEMP8U_TO_REG(val - data->temp2_offset);
+               else
+                       temp = TEMP8_TO_REG(val - data->temp2_offset);
+       } else {
+               temp = TEMP8_TO_REG(val);
+       }
+       data->temp8[nr] = temp;
+       i2c_smbus_write_byte_data(client, reg, temp);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -297,28 +396,56 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct lm63_data *data = lm63_update_device(dev);
-       return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])
-                      + data->temp2_offset);
+       int nr = attr->index;
+       int temp;
+
+       if (!nr) {
+               /*
+                * Use unsigned temperature unless its value is zero.
+                * If it is zero, use signed temperature.
+                */
+               if (data->temp11u)
+                       temp = TEMP11_FROM_REG(data->temp11u);
+               else
+                       temp = TEMP11_FROM_REG(data->temp11[nr]);
+       } else {
+               if (data->remote_unsigned && nr == 2)
+                       temp = TEMP11_FROM_REG((u16)data->temp11[nr]);
+               else
+                       temp = TEMP11_FROM_REG(data->temp11[nr]);
+       }
+       return sprintf(buf, "%d\n", temp + data->temp2_offset);
 }
 
 static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
                          const char *buf, size_t count)
 {
-       static const u8 reg[4] = {
+       static const u8 reg[6] = {
                LM63_REG_REMOTE_LOW_MSB,
                LM63_REG_REMOTE_LOW_LSB,
                LM63_REG_REMOTE_HIGH_MSB,
                LM63_REG_REMOTE_HIGH_LSB,
+               LM63_REG_REMOTE_OFFSET_MSB,
+               LM63_REG_REMOTE_OFFSET_LSB,
        };
 
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
-       long val = simple_strtol(buf, NULL, 10);
+       long val;
+       int err;
        int nr = attr->index;
 
+       err = kstrtol(buf, 10, &val);
+       if (err)
+               return err;
+
        mutex_lock(&data->update_lock);
-       data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
+       if (data->remote_unsigned && nr == 2)
+               data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset);
+       else
+               data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
+
        i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
                                  data->temp11[nr] >> 8);
        i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
@@ -327,35 +454,143 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
        return count;
 }
 
-/* Hysteresis register holds a relative value, while we want to present
-   an absolute to user-space */
-static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
-                                   char *buf)
+/*
+ * Hysteresis register holds a relative value, while we want to present
+ * an absolute to user-space
+ */
+static ssize_t show_temp2_crit_hyst(struct device *dev,
+                                   struct device_attribute *dummy, char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
-       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
+       return sprintf(buf, "%d\n", temp8_from_reg(data, 2)
                       + data->temp2_offset
                       - TEMP8_FROM_REG(data->temp2_crit_hyst));
 }
 
-/* And now the other way around, user-space provides an absolute
-   hysteresis value and we have to store a relative one */
-static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+static ssize_t show_lut_temp_hyst(struct device *dev,
+                                 struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+
+       return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
+                      + data->temp2_offset
+                      - TEMP8_FROM_REG(data->lut_temp_hyst));
+}
+
+/*
+ * And now the other way around, user-space provides an absolute
+ * hysteresis value and we have to store a relative one
+ */
+static ssize_t set_temp2_crit_hyst(struct device *dev,
+                                  struct device_attribute *dummy,
                                   const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
-       long val = simple_strtol(buf, NULL, 10);
+       long val;
+       int err;
        long hyst;
 
+       err = kstrtol(buf, 10, &val);
+       if (err)
+               return err;
+
        mutex_lock(&data->update_lock);
-       hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val;
+       hyst = temp8_from_reg(data, 2) + data->temp2_offset - val;
        i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
                                  HYST_TO_REG(hyst));
        mutex_unlock(&data->update_lock);
        return count;
 }
 
+/*
+ * Set conversion rate.
+ * client->update_lock must be held when calling this function.
+ */
+static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
+                             unsigned int interval)
+{
+       int i;
+       unsigned int update_interval;
+
+       /* Shift calculations to avoid rounding errors */
+       interval <<= 6;
+
+       /* find the nearest update rate */
+       update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
+         / data->max_convrate_hz;
+       for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
+               if (interval >= update_interval * 3 / 4)
+                       break;
+
+       i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
+       data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
+}
+
+static ssize_t show_update_interval(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct lm63_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", data->update_interval);
+}
+
+static ssize_t set_update_interval(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+       unsigned long val;
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err)
+               return err;
+
+       mutex_lock(&data->update_lock);
+       lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t show_type(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+
+       return sprintf(buf, data->trutherm ? "1\n" : "2\n");
+}
+
+static ssize_t set_type(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+       unsigned long val;
+       int ret;
+       u8 reg;
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret < 0)
+               return ret;
+       if (val != 1 && val != 2)
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+       data->trutherm = val == 1;
+       reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02;
+       i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM,
+                                 reg | (data->trutherm ? 0x02 : 0x00));
+       data->valid = 0;
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
 static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
                           char *buf)
 {
@@ -377,27 +612,87 @@ static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
        set_fan, 1);
 
-static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
+       show_lut_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
+       show_lut_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
+       show_lut_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
+       show_lut_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
+       show_lut_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
+       show_lut_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
+       show_lut_temp, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
+       show_lut_temp, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO,
+       show_lut_temp, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO,
+       show_lut_temp, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO,
+       show_lut_temp, NULL, 13);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 13);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO,
+       show_lut_temp, NULL, 14);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO,
+       show_lut_temp_hyst, NULL, 14);
 
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
-       set_local_temp8, 1);
+       set_temp8, 1);
 
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
        set_temp11, 1);
 static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
        set_temp11, 2);
-/*
- * On LM63, temp2_crit can be set only once, which should be job
- * of the bootloader.
- */
+static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 3);
 static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
-       NULL, 2);
+       set_temp8, 2);
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
        set_temp2_crit_hyst);
 
+static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type);
+
 /* Individual alarm files */
 static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
@@ -408,14 +703,43 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
 /* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
+                  set_update_interval);
+
 static struct attribute *lm63_attributes[] = {
-       &dev_attr_pwm1.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
        &dev_attr_pwm1_enable.attr,
+       &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point5_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point6_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point7_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point8_temp_hyst.dev_attr.attr,
+
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp2_input.dev_attr.attr,
        &sensor_dev_attr_temp2_min.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_offset.dev_attr.attr,
        &sensor_dev_attr_temp2_crit.dev_attr.attr,
        &dev_attr_temp2_crit_hyst.attr,
 
@@ -425,10 +749,54 @@ static struct attribute *lm63_attributes[] = {
        &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
        &dev_attr_alarms.attr,
+       &dev_attr_update_interval.attr,
        NULL
 };
 
+static struct attribute *lm63_attributes_extra_lut[] = {
+       &sensor_dev_attr_pwm1_auto_point9_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point9_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point9_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point10_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point10_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point10_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point11_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point11_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point11_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point12_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point12_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point12_temp_hyst.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group lm63_group_extra_lut = {
+       .attrs = lm63_attributes_extra_lut,
+};
+
+/*
+ * On LM63, temp2_crit can be set only once, which should be job
+ * of the bootloader.
+ * On LM64, temp2_crit can always be set.
+ * On LM96163, temp2_crit can be set if bit 1 of the configuration
+ * register is true.
+ */
+static umode_t lm63_attribute_mode(struct kobject *kobj,
+                                  struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+
+       if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr
+           && (data->kind == lm64 ||
+               (data->kind == lm96163 && (data->config & 0x02))))
+               return attr->mode | S_IWUSR;
+
+       return attr->mode;
+}
+
 static const struct attribute_group lm63_group = {
+       .is_visible = lm63_attribute_mode,
        .attrs = lm63_attributes,
 };
 
@@ -487,6 +855,8 @@ static int lm63_detect(struct i2c_client *new_client,
                strlcpy(info->type, "lm63", I2C_NAME_SIZE);
        else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
                strlcpy(info->type, "lm64", I2C_NAME_SIZE);
+       else if (chip_id == 0x49 && address == 0x4c)
+               strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
        else
                return -ENODEV;
 
@@ -518,12 +888,24 @@ static int lm63_probe(struct i2c_client *new_client,
        lm63_init_client(new_client);
 
        /* Register sysfs hooks */
-       if ((err = sysfs_create_group(&new_client->dev.kobj,
-                                     &lm63_group)))
+       err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
+       if (err)
                goto exit_free;
        if (data->config & 0x04) { /* tachometer enabled */
-               if ((err = sysfs_create_group(&new_client->dev.kobj,
-                                             &lm63_group_fan1)))
+               err = sysfs_create_group(&new_client->dev.kobj,
+                                        &lm63_group_fan1);
+               if (err)
+                       goto exit_remove_files;
+       }
+       if (data->kind == lm96163) {
+               err = device_create_file(&new_client->dev,
+                                        &dev_attr_temp2_type);
+               if (err)
+                       goto exit_remove_files;
+
+               err = sysfs_create_group(&new_client->dev.kobj,
+                                        &lm63_group_extra_lut);
+               if (err)
                        goto exit_remove_files;
        }
 
@@ -538,17 +920,25 @@ static int lm63_probe(struct i2c_client *new_client,
 exit_remove_files:
        sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
        sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
+       if (data->kind == lm96163) {
+               device_remove_file(&new_client->dev, &dev_attr_temp2_type);
+               sysfs_remove_group(&new_client->dev.kobj,
+                                  &lm63_group_extra_lut);
+       }
 exit_free:
        kfree(data);
 exit:
        return err;
 }
 
-/* Idealy we shouldn't have to initialize anything, since the BIOS
-   should have taken care of everything */
+/*
+ * Ideally we shouldn't have to initialize anything, since the BIOS
+ * should have taken care of everything
+ */
 static void lm63_init_client(struct i2c_client *client)
 {
        struct lm63_data *data = i2c_get_clientdata(client);
+       u8 convrate;
 
        data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
        data->config_fan = i2c_smbus_read_byte_data(client,
@@ -561,16 +951,57 @@ static void lm63_init_client(struct i2c_client *client)
                i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
                                          data->config);
        }
+       /* Tachometer is always enabled on LM64 */
+       if (data->kind == lm64)
+               data->config |= 0x04;
 
        /* We may need pwm1_freq before ever updating the client data */
        data->pwm1_freq = i2c_smbus_read_byte_data(client, LM63_REG_PWM_FREQ);
        if (data->pwm1_freq == 0)
                data->pwm1_freq = 1;
 
+       switch (data->kind) {
+       case lm63:
+       case lm64:
+               data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
+               data->lut_size = 8;
+               break;
+       case lm96163:
+               data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
+               data->lut_size = 12;
+               data->trutherm
+                 = i2c_smbus_read_byte_data(client,
+                                            LM96163_REG_TRUTHERM) & 0x02;
+               break;
+       }
+       convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
+       if (unlikely(convrate > LM63_MAX_CONVRATE))
+               convrate = LM63_MAX_CONVRATE;
+       data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
+                                               convrate);
+
+       /*
+        * For LM96163, check if high resolution PWM
+        * and unsigned temperature format is enabled.
+        */
+       if (data->kind == lm96163) {
+               u8 config_enhanced
+                 = i2c_smbus_read_byte_data(client,
+                                            LM96163_REG_CONFIG_ENHANCED);
+               if (config_enhanced & 0x20)
+                       data->lut_temp_highres = true;
+               if ((config_enhanced & 0x10)
+                   && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
+                       data->pwm_highres = true;
+               if (config_enhanced & 0x08)
+                       data->remote_unsigned = true;
+       }
+
        /* Show some debug info about the LM63 configuration */
-       dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
-               (data->config & 0x04) ? "tachometer input" :
-               "alert output");
+       if (data->kind == lm63)
+               dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
+                       (data->config & 0x04) ? "tachometer input" :
+                       "alert output");
        dev_dbg(&client->dev, "PWM clock %s kHz, output frequency %u Hz\n",
                (data->config_fan & 0x08) ? "1.4" : "360",
                ((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq);
@@ -586,6 +1017,10 @@ static int lm63_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm63_group);
        sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
+       if (data->kind == lm96163) {
+               device_remove_file(&client->dev, &dev_attr_temp2_type);
+               sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
+       }
 
        kfree(data);
        return 0;
@@ -595,10 +1030,15 @@ static struct lm63_data *lm63_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
+       unsigned long next_update;
+       int i;
 
        mutex_lock(&data->update_lock);
 
-       if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+       next_update = data->last_updated
+         + msecs_to_jiffies(data->update_interval) + 1;
+
+       if (time_after(jiffies, next_update) || !data->valid) {
                if (data->config & 0x04) { /* tachometer enabled  */
                        /* order matters for fan1_input */
                        data->fan[0] = i2c_smbus_read_byte_data(client,
@@ -615,8 +1055,8 @@ static struct lm63_data *lm63_update_device(struct device *dev)
                                  LM63_REG_PWM_FREQ);
                if (data->pwm1_freq == 0)
                        data->pwm1_freq = 1;
-               data->pwm1_value = i2c_smbus_read_byte_data(client,
-                                  LM63_REG_PWM_VALUE);
+               data->pwm1[0] = i2c_smbus_read_byte_data(client,
+                               LM63_REG_PWM_VALUE);
 
                data->temp8[0] = i2c_smbus_read_byte_data(client,
                                 LM63_REG_LOCAL_TEMP);
@@ -636,6 +1076,17 @@ static struct lm63_data *lm63_update_device(struct device *dev)
                                  LM63_REG_REMOTE_HIGH_MSB) << 8)
                                | i2c_smbus_read_byte_data(client,
                                  LM63_REG_REMOTE_HIGH_LSB);
+               data->temp11[3] = (i2c_smbus_read_byte_data(client,
+                                 LM63_REG_REMOTE_OFFSET_MSB) << 8)
+                               | i2c_smbus_read_byte_data(client,
+                                 LM63_REG_REMOTE_OFFSET_LSB);
+
+               if (data->kind == lm96163)
+                       data->temp11u = (i2c_smbus_read_byte_data(client,
+                                       LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
+                                     | i2c_smbus_read_byte_data(client,
+                                       LM96163_REG_REMOTE_TEMP_U_LSB);
+
                data->temp8[2] = i2c_smbus_read_byte_data(client,
                                 LM63_REG_REMOTE_TCRIT);
                data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
@@ -648,6 +1099,21 @@ static struct lm63_data *lm63_update_device(struct device *dev)
                data->valid = 1;
        }
 
+       if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
+           !data->lut_valid) {
+               for (i = 0; i < data->lut_size; i++) {
+                       data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
+                                           LM63_REG_LUT_PWM(i));
+                       data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
+                                            LM63_REG_LUT_TEMP(i));
+               }
+               data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
+                                     LM63_REG_LUT_TEMP_HYST);
+
+               data->lut_last_updated = jiffies;
+               data->lut_valid = 1;
+       }
+
        mutex_unlock(&data->update_lock);
 
        return data;
index bdfd675488aeb5e64b9d4c144c5cfd185ad0ecb0..d2dd5f90496df1ca4393467e31f1ab78264f17d8 100644 (file)
@@ -917,7 +917,7 @@ static ssize_t set_update_interval(struct device *dev,
                return err;
 
        mutex_lock(&data->update_lock);
-       lm90_set_convrate(client, data, val);
+       lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
        mutex_unlock(&data->update_lock);
 
        return count;
index 84ef3a898707ec4bd572c04f4be75836d036a8c3..482ca901db30b61632773176a4131be60a200575 100644 (file)
@@ -106,11 +106,14 @@ static ssize_t show_adc(struct device *dev,
        if (ret < 0)
                return ret;
 
-       return sprintf(buf, "%d\n", ret);
+       /* assume the reference voltage to be 2.048V, with an 8-bit sample,
+        * the LSB weight is 8mV
+        */
+       return sprintf(buf, "%d\n", ret * 8);
 }
 
 #define MAX1111_ADC_ATTR(_id)          \
-       SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id)
+       SENSOR_DEVICE_ATTR(in##_id##_input, S_IRUGO, show_adc, NULL, _id)
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 static MAX1111_ADC_ATTR(0);
@@ -120,10 +123,10 @@ static MAX1111_ADC_ATTR(3);
 
 static struct attribute *max1111_attributes[] = {
        &dev_attr_name.attr,
-       &sensor_dev_attr_adc0_in.dev_attr.attr,
-       &sensor_dev_attr_adc1_in.dev_attr.attr,
-       &sensor_dev_attr_adc2_in.dev_attr.attr,
-       &sensor_dev_attr_adc3_in.dev_attr.attr,
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
        NULL,
 };
 
index 996302ae210e7b1fe9686a6425662d49f83c4dc3..4a6d5cef3964c910dc8982198c6b7ea921096394 100644 (file)
@@ -26,7 +26,7 @@ config MEDIA_TUNER
        select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL
        select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
@@ -116,6 +116,13 @@ config MEDIA_TUNER_MT2060
        help
          A driver for the silicon IF tuner MT2060 from Microtune.
 
+config MEDIA_TUNER_MT2063
+       tristate "Microtune MT2063 silicon IF tuner"
+       depends on VIDEO_MEDIA && I2C
+       default m if MEDIA_TUNER_CUSTOMISE
+       help
+         A driver for the silicon IF tuner MT2063 from Microtune.
+
 config MEDIA_TUNER_MT2266
        tristate "Microtune MT2266 silicon tuner"
        depends on VIDEO_MEDIA && I2C
index 196c12a55f9aa7e3d1fefa80d54d6a605c5425ee..8295854ab94bc7923bd85483b7e1b3a6d4ec9256 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
 obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
index 9883617b78620a4e813bcfe3b7451a5430b60e44..cb2c98fbad1ba066d839ace44fe8a6fb5c500024 100644 (file)
@@ -151,7 +151,7 @@ static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw)
 {
        u8 val;
 
-       if (bw == BANDWIDTH_8_MHZ)
+       if (bw == 8000000)
                val = priv->bb_filter_8mhz_cfg;
        else
                val = priv->bb_filter_7mhz_cfg;
@@ -257,39 +257,28 @@ static void max2165_debug_status(struct max2165_priv *priv)
        dprintk("VCO: %d, VCO Sub-band: %d, ADC: %d\n", vco, vco_sub_band, adc);
 }
 
-static int max2165_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int max2165_set_params(struct dvb_frontend *fe)
 {
        struct max2165_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret;
 
-       dprintk("%s() frequency=%d (Hz)\n", __func__, params->frequency);
-       if (fe->ops.info.type == FE_ATSC) {
-                       return -EINVAL;
-       } else if (fe->ops.info.type == FE_OFDM) {
-               dprintk("%s() OFDM\n", __func__);
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       return -EINVAL;
-               case BANDWIDTH_7_MHZ:
-               case BANDWIDTH_8_MHZ:
-                       priv->frequency = params->frequency;
-                       priv->bandwidth = params->u.ofdm.bandwidth;
-                       break;
-               default:
-                       printk(KERN_ERR "MAX2165 bandwidth not set!\n");
-                       return -EINVAL;
-               }
-       } else {
-               printk(KERN_ERR "MAX2165 modulation type not supported!\n");
+       switch (c->bandwidth_hz) {
+       case 7000000:
+       case 8000000:
+               priv->frequency = c->frequency;
+               break;
+       default:
+               printk(KERN_INFO "MAX2165: bandwidth %d Hz not supported.\n",
+                      c->bandwidth_hz);
                return -EINVAL;
        }
 
-       dprintk("%s() frequency=%d\n", __func__, priv->frequency);
+       dprintk("%s() frequency=%d\n", __func__, c->frequency);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       max2165_set_bandwidth(priv, priv->bandwidth);
+       max2165_set_bandwidth(priv, c->bandwidth_hz);
        ret = max2165_set_rf(priv, priv->frequency);
        mdelay(50);
        max2165_debug_status(priv);
@@ -370,7 +359,7 @@ static int max2165_init(struct dvb_frontend *fe)
 
        max2165_read_rom_table(priv);
 
-       max2165_set_bandwidth(priv, BANDWIDTH_8_MHZ);
+       max2165_set_bandwidth(priv, 8000000);
 
        if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
index fe5c4b8d83eeddaa203806da48726822e93eeb49..5ddce7e326f743043d8cdaa87c5c1f3ca8c079d4 100644 (file)
@@ -214,22 +214,22 @@ exit:
        return err;
 }
 
-static int mc44s803_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int mc44s803_set_params(struct dvb_frontend *fe)
 {
        struct mc44s803_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 r1, r2, n1, n2, lo1, lo2, freq, val;
        int err;
 
-       priv->frequency = params->frequency;
+       priv->frequency = c->frequency;
 
        r1 = MC44S803_OSC / 1000000;
        r2 = MC44S803_OSC /  100000;
 
-       n1 = (params->frequency + MC44S803_IF1 + 500000) / 1000000;
+       n1 = (c->frequency + MC44S803_IF1 + 500000) / 1000000;
        freq = MC44S803_OSC / r1 * n1;
        lo1 = ((60 * n1) + (r1 / 2)) / r1;
-       freq = freq - params->frequency;
+       freq = freq - c->frequency;
 
        n2 = (freq - MC44S803_IF2 + 50000) / 100000;
        lo2 = ((60 * n2) + (r2 / 2)) / r2;
index 2d0e7689c6a224eae8757c5c054972f1ab03d2a6..13381de58a843a4b8f4997705bdfc62c40ae34f5 100644 (file)
@@ -153,8 +153,9 @@ static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
 #define IF2  36150       // IF2 frequency = 36.150 MHz
 #define FREF 16000       // Quartz oscillator 16 MHz
 
-static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int mt2060_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct mt2060_priv *priv;
        int ret=0;
        int i=0;
@@ -176,8 +177,7 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
 
        mt2060_writeregs(priv,b,2);
 
-       freq = params->frequency / 1000; // Hz -> kHz
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+       freq = c->frequency / 1000; /* Hz -> kHz */
 
        f_lo1 = freq + if1 * 1000;
        f_lo1 = (f_lo1 / 250) * 250;
@@ -293,10 +293,9 @@ static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
-static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+static int mt2060_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-       struct mt2060_priv *priv = fe->tuner_priv;
-       *bandwidth = priv->bandwidth;
+       *frequency = IF2 * 1000;
        return 0;
 }
 
@@ -356,7 +355,7 @@ static const struct dvb_tuner_ops mt2060_tuner_ops = {
 
        .set_params    = mt2060_set_params,
        .get_frequency = mt2060_get_frequency,
-       .get_bandwidth = mt2060_get_bandwidth
+       .get_if_frequency = mt2060_get_if_frequency,
 };
 
 /* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
index 5eaccdefd0b056222664dc0d0ca68555b0269654..2b60de6c707dfd884812376358089fde51600233 100644 (file)
@@ -97,7 +97,6 @@ struct mt2060_priv {
        struct i2c_adapter   *i2c;
 
        u32 frequency;
-       u32 bandwidth;
        u16 if1_freq;
        u8  fmfreq;
 };
diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/common/tuners/mt2063.c
new file mode 100644 (file)
index 0000000..c89af3c
--- /dev/null
@@ -0,0 +1,2307 @@
+/*
+ * Driver for mt2063 Micronas tuner
+ *
+ * Copyright (c) 2011 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This driver came from a driver originally written by:
+ *             Henry Wang <Henry.wang@AzureWave.com>
+ * Made publicly available by Terratec, at:
+ *     http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
+ * The original driver's license is GPL, as declared with MODULE_LICENSE()
+ *
+ * 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 under 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/videodev2.h>
+
+#include "mt2063.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Set Verbosity level");
+
+#define dprintk(level, fmt, arg...) do {                               \
+if (debug >= level)                                                    \
+       printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg); \
+} while (0)
+
+
+/* positive error codes used internally */
+
+/*  Info: Unavoidable LO-related spur may be present in the output  */
+#define MT2063_SPUR_PRESENT_ERR             (0x00800000)
+
+/*  Info: Mask of bits used for # of LO-related spurs that were avoided during tuning  */
+#define MT2063_SPUR_CNT_MASK                (0x001f0000)
+#define MT2063_SPUR_SHIFT                   (16)
+
+/*  Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
+#define MT2063_UPC_RANGE                    (0x04000000)
+
+/*  Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
+#define MT2063_DNC_RANGE                    (0x08000000)
+
+/*
+ *  Constant defining the version of the following structure
+ *  and therefore the API for this code.
+ *
+ *  When compiling the tuner driver, the preprocessor will
+ *  check against this version number to make sure that
+ *  it matches the version that the tuner driver knows about.
+ */
+
+/* DECT Frequency Avoidance */
+#define MT2063_DECT_AVOID_US_FREQS      0x00000001
+
+#define MT2063_DECT_AVOID_EURO_FREQS    0x00000002
+
+#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
+
+#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
+
+enum MT2063_DECT_Avoid_Type {
+       MT2063_NO_DECT_AVOIDANCE = 0,                           /* Do not create DECT exclusion zones.     */
+       MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS,      /* Avoid US DECT frequencies.              */
+       MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS,  /* Avoid European DECT frequencies.        */
+       MT2063_AVOID_BOTH                                       /* Avoid both regions. Not typically used. */
+};
+
+#define MT2063_MAX_ZONES 48
+
+struct MT2063_ExclZone_t {
+       u32 min_;
+       u32 max_;
+       struct MT2063_ExclZone_t *next_;
+};
+
+/*
+ *  Structure of data needed for Spur Avoidance
+ */
+struct MT2063_AvoidSpursData_t {
+       u32 f_ref;
+       u32 f_in;
+       u32 f_LO1;
+       u32 f_if1_Center;
+       u32 f_if1_Request;
+       u32 f_if1_bw;
+       u32 f_LO2;
+       u32 f_out;
+       u32 f_out_bw;
+       u32 f_LO1_Step;
+       u32 f_LO2_Step;
+       u32 f_LO1_FracN_Avoid;
+       u32 f_LO2_FracN_Avoid;
+       u32 f_zif_bw;
+       u32 f_min_LO_Separation;
+       u32 maxH1;
+       u32 maxH2;
+       enum MT2063_DECT_Avoid_Type avoidDECT;
+       u32 bSpurPresent;
+       u32 bSpurAvoided;
+       u32 nSpursFound;
+       u32 nZones;
+       struct MT2063_ExclZone_t *freeZones;
+       struct MT2063_ExclZone_t *usedZones;
+       struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
+};
+
+/*
+ * Parameter for function MT2063_SetPowerMask that specifies the power down
+ * of various sections of the MT2063.
+ */
+enum MT2063_Mask_Bits {
+       MT2063_REG_SD = 0x0040,         /* Shutdown regulator                 */
+       MT2063_SRO_SD = 0x0020,         /* Shutdown SRO                       */
+       MT2063_AFC_SD = 0x0010,         /* Shutdown AFC A/D                   */
+       MT2063_PD_SD = 0x0002,          /* Enable power detector shutdown     */
+       MT2063_PDADC_SD = 0x0001,       /* Enable power detector A/D shutdown */
+       MT2063_VCO_SD = 0x8000,         /* Enable VCO shutdown                */
+       MT2063_LTX_SD = 0x4000,         /* Enable LTX shutdown                */
+       MT2063_LT1_SD = 0x2000,         /* Enable LT1 shutdown                */
+       MT2063_LNA_SD = 0x1000,         /* Enable LNA shutdown                */
+       MT2063_UPC_SD = 0x0800,         /* Enable upconverter shutdown        */
+       MT2063_DNC_SD = 0x0400,         /* Enable downconverter shutdown      */
+       MT2063_VGA_SD = 0x0200,         /* Enable VGA shutdown                */
+       MT2063_AMP_SD = 0x0100,         /* Enable AMP shutdown                */
+       MT2063_ALL_SD = 0xFF73,         /* All shutdown bits for this tuner   */
+       MT2063_NONE_SD = 0x0000         /* No shutdown bits                   */
+};
+
+/*
+ *  Possible values for MT2063_DNC_OUTPUT
+ */
+enum MT2063_DNC_Output_Enable {
+       MT2063_DNC_NONE = 0,
+       MT2063_DNC_1,
+       MT2063_DNC_2,
+       MT2063_DNC_BOTH
+};
+
+/*
+ *  Two-wire serial bus subaddresses of the tuner registers.
+ *  Also known as the tuner's register addresses.
+ */
+enum MT2063_Register_Offsets {
+       MT2063_REG_PART_REV = 0,        /*  0x00: Part/Rev Code         */
+       MT2063_REG_LO1CQ_1,             /*  0x01: LO1C Queued Byte 1    */
+       MT2063_REG_LO1CQ_2,             /*  0x02: LO1C Queued Byte 2    */
+       MT2063_REG_LO2CQ_1,             /*  0x03: LO2C Queued Byte 1    */
+       MT2063_REG_LO2CQ_2,             /*  0x04: LO2C Queued Byte 2    */
+       MT2063_REG_LO2CQ_3,             /*  0x05: LO2C Queued Byte 3    */
+       MT2063_REG_RSVD_06,             /*  0x06: Reserved              */
+       MT2063_REG_LO_STATUS,           /*  0x07: LO Status             */
+       MT2063_REG_FIFFC,               /*  0x08: FIFF Center           */
+       MT2063_REG_CLEARTUNE,           /*  0x09: ClearTune Filter      */
+       MT2063_REG_ADC_OUT,             /*  0x0A: ADC_OUT               */
+       MT2063_REG_LO1C_1,              /*  0x0B: LO1C Byte 1           */
+       MT2063_REG_LO1C_2,              /*  0x0C: LO1C Byte 2           */
+       MT2063_REG_LO2C_1,              /*  0x0D: LO2C Byte 1           */
+       MT2063_REG_LO2C_2,              /*  0x0E: LO2C Byte 2           */
+       MT2063_REG_LO2C_3,              /*  0x0F: LO2C Byte 3           */
+       MT2063_REG_RSVD_10,             /*  0x10: Reserved              */
+       MT2063_REG_PWR_1,               /*  0x11: PWR Byte 1            */
+       MT2063_REG_PWR_2,               /*  0x12: PWR Byte 2            */
+       MT2063_REG_TEMP_STATUS,         /*  0x13: Temp Status           */
+       MT2063_REG_XO_STATUS,           /*  0x14: Crystal Status        */
+       MT2063_REG_RF_STATUS,           /*  0x15: RF Attn Status        */
+       MT2063_REG_FIF_STATUS,          /*  0x16: FIF Attn Status       */
+       MT2063_REG_LNA_OV,              /*  0x17: LNA Attn Override     */
+       MT2063_REG_RF_OV,               /*  0x18: RF Attn Override      */
+       MT2063_REG_FIF_OV,              /*  0x19: FIF Attn Override     */
+       MT2063_REG_LNA_TGT,             /*  0x1A: Reserved              */
+       MT2063_REG_PD1_TGT,             /*  0x1B: Pwr Det 1 Target      */
+       MT2063_REG_PD2_TGT,             /*  0x1C: Pwr Det 2 Target      */
+       MT2063_REG_RSVD_1D,             /*  0x1D: Reserved              */
+       MT2063_REG_RSVD_1E,             /*  0x1E: Reserved              */
+       MT2063_REG_RSVD_1F,             /*  0x1F: Reserved              */
+       MT2063_REG_RSVD_20,             /*  0x20: Reserved              */
+       MT2063_REG_BYP_CTRL,            /*  0x21: Bypass Control        */
+       MT2063_REG_RSVD_22,             /*  0x22: Reserved              */
+       MT2063_REG_RSVD_23,             /*  0x23: Reserved              */
+       MT2063_REG_RSVD_24,             /*  0x24: Reserved              */
+       MT2063_REG_RSVD_25,             /*  0x25: Reserved              */
+       MT2063_REG_RSVD_26,             /*  0x26: Reserved              */
+       MT2063_REG_RSVD_27,             /*  0x27: Reserved              */
+       MT2063_REG_FIFF_CTRL,           /*  0x28: FIFF Control          */
+       MT2063_REG_FIFF_OFFSET,         /*  0x29: FIFF Offset           */
+       MT2063_REG_CTUNE_CTRL,          /*  0x2A: Reserved              */
+       MT2063_REG_CTUNE_OV,            /*  0x2B: Reserved              */
+       MT2063_REG_CTRL_2C,             /*  0x2C: Reserved              */
+       MT2063_REG_FIFF_CTRL2,          /*  0x2D: Fiff Control          */
+       MT2063_REG_RSVD_2E,             /*  0x2E: Reserved              */
+       MT2063_REG_DNC_GAIN,            /*  0x2F: DNC Control           */
+       MT2063_REG_VGA_GAIN,            /*  0x30: VGA Gain Ctrl         */
+       MT2063_REG_RSVD_31,             /*  0x31: Reserved              */
+       MT2063_REG_TEMP_SEL,            /*  0x32: Temperature Selection */
+       MT2063_REG_RSVD_33,             /*  0x33: Reserved              */
+       MT2063_REG_RSVD_34,             /*  0x34: Reserved              */
+       MT2063_REG_RSVD_35,             /*  0x35: Reserved              */
+       MT2063_REG_RSVD_36,             /*  0x36: Reserved              */
+       MT2063_REG_RSVD_37,             /*  0x37: Reserved              */
+       MT2063_REG_RSVD_38,             /*  0x38: Reserved              */
+       MT2063_REG_RSVD_39,             /*  0x39: Reserved              */
+       MT2063_REG_RSVD_3A,             /*  0x3A: Reserved              */
+       MT2063_REG_RSVD_3B,             /*  0x3B: Reserved              */
+       MT2063_REG_RSVD_3C,             /*  0x3C: Reserved              */
+       MT2063_REG_END_REGS
+};
+
+struct mt2063_state {
+       struct i2c_adapter *i2c;
+
+       bool init;
+
+       const struct mt2063_config *config;
+       struct dvb_tuner_ops ops;
+       struct dvb_frontend *frontend;
+       struct tuner_state status;
+
+       u32 frequency;
+       u32 srate;
+       u32 bandwidth;
+       u32 reference;
+
+       u32 tuner_id;
+       struct MT2063_AvoidSpursData_t AS_Data;
+       u32 f_IF1_actual;
+       u32 rcvr_mode;
+       u32 ctfilt_sw;
+       u32 CTFiltMax[31];
+       u32 num_regs;
+       u8 reg[MT2063_REG_END_REGS];
+};
+
+/*
+ * mt2063_write - Write data into the I2C bus
+ */
+static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
+{
+       struct dvb_frontend *fe = state->frontend;
+       int ret;
+       u8 buf[60];
+       struct i2c_msg msg = {
+               .addr = state->config->tuner_address,
+               .flags = 0,
+               .buf = buf,
+               .len = len + 1
+       };
+
+       dprintk(2, "\n");
+
+       msg.buf[0] = reg;
+       memcpy(msg.buf + 1, data, len);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       ret = i2c_transfer(state->i2c, &msg, 1);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (ret < 0)
+               printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
+
+       return ret;
+}
+
+/*
+ * mt2063_write - Write register data into the I2C bus, caching the value
+ */
+static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
+{
+       u32 status;
+
+       dprintk(2, "\n");
+
+       if (reg >= MT2063_REG_END_REGS)
+               return -ERANGE;
+
+       status = mt2063_write(state, reg, &val, 1);
+       if (status < 0)
+               return status;
+
+       state->reg[reg] = val;
+
+       return 0;
+}
+
+/*
+ * mt2063_read - Read data from the I2C bus
+ */
+static u32 mt2063_read(struct mt2063_state *state,
+                          u8 subAddress, u8 *pData, u32 cnt)
+{
+       u32 status = 0; /* Status to be returned        */
+       struct dvb_frontend *fe = state->frontend;
+       u32 i = 0;
+
+       dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       for (i = 0; i < cnt; i++) {
+               u8 b0[] = { subAddress + i };
+               struct i2c_msg msg[] = {
+                       {
+                               .addr = state->config->tuner_address,
+                               .flags = 0,
+                               .buf = b0,
+                               .len = 1
+                       }, {
+                               .addr = state->config->tuner_address,
+                               .flags = I2C_M_RD,
+                               .buf = pData + i,
+                               .len = 1
+                       }
+               };
+
+               status = i2c_transfer(state->i2c, msg, 2);
+               dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
+                          subAddress + i, status, *(pData + i));
+               if (status < 0)
+                       break;
+       }
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (status < 0)
+               printk(KERN_ERR "Can't read from address 0x%02x,\n",
+                      subAddress + i);
+
+       return status;
+}
+
+/*
+ * FIXME: Is this really needed?
+ */
+static int MT2063_Sleep(struct dvb_frontend *fe)
+{
+       /*
+        *  ToDo:  Add code here to implement a OS blocking
+        */
+       msleep(10);
+
+       return 0;
+}
+
+/*
+ * Microtune spur avoidance
+ */
+
+/*  Implement ceiling, floor functions.  */
+#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
+#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
+
+struct MT2063_FIFZone_t {
+       s32 min_;
+       s32 max_;
+};
+
+static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
+                                           *pAS_Info,
+                                           struct MT2063_ExclZone_t *pPrevNode)
+{
+       struct MT2063_ExclZone_t *pNode;
+
+       dprintk(2, "\n");
+
+       /*  Check for a node in the free list  */
+       if (pAS_Info->freeZones != NULL) {
+               /*  Use one from the free list  */
+               pNode = pAS_Info->freeZones;
+               pAS_Info->freeZones = pNode->next_;
+       } else {
+               /*  Grab a node from the array  */
+               pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
+       }
+
+       if (pPrevNode != NULL) {
+               pNode->next_ = pPrevNode->next_;
+               pPrevNode->next_ = pNode;
+       } else {                /*  insert at the beginning of the list  */
+
+               pNode->next_ = pAS_Info->usedZones;
+               pAS_Info->usedZones = pNode;
+       }
+
+       pAS_Info->nZones++;
+       return pNode;
+}
+
+static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
+                                           *pAS_Info,
+                                           struct MT2063_ExclZone_t *pPrevNode,
+                                           struct MT2063_ExclZone_t
+                                           *pNodeToRemove)
+{
+       struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
+
+       dprintk(2, "\n");
+
+       /*  Make previous node point to the subsequent node  */
+       if (pPrevNode != NULL)
+               pPrevNode->next_ = pNext;
+
+       /*  Add pNodeToRemove to the beginning of the freeZones  */
+       pNodeToRemove->next_ = pAS_Info->freeZones;
+       pAS_Info->freeZones = pNodeToRemove;
+
+       /*  Decrement node count  */
+       pAS_Info->nZones--;
+
+       return pNext;
+}
+
+/*
+ * MT_AddExclZone()
+ *
+ * Add (and merge) an exclusion zone into the list.
+ * If the range (f_min, f_max) is totally outside the
+ * 1st IF BW, ignore the entry.
+ * If the range (f_min, f_max) is negative, ignore the entry.
+ */
+static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
+                              u32 f_min, u32 f_max)
+{
+       struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
+       struct MT2063_ExclZone_t *pPrev = NULL;
+       struct MT2063_ExclZone_t *pNext = NULL;
+
+       dprintk(2, "\n");
+
+       /*  Check to see if this overlaps the 1st IF filter  */
+       if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
+           && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
+           && (f_min < f_max)) {
+               /*
+                *                1        2         3      4       5        6
+                *
+                *   New entry:  |---|    |--|      |--|    |-|    |---|    |--|
+                *                or       or        or     or      or
+                *   Existing:  |--|      |--|      |--|    |---|  |-|      |--|
+                */
+
+               /*  Check for our place in the list  */
+               while ((pNode != NULL) && (pNode->max_ < f_min)) {
+                       pPrev = pNode;
+                       pNode = pNode->next_;
+               }
+
+               if ((pNode != NULL) && (pNode->min_ < f_max)) {
+                       /*  Combine me with pNode  */
+                       if (f_min < pNode->min_)
+                               pNode->min_ = f_min;
+                       if (f_max > pNode->max_)
+                               pNode->max_ = f_max;
+               } else {
+                       pNode = InsertNode(pAS_Info, pPrev);
+                       pNode->min_ = f_min;
+                       pNode->max_ = f_max;
+               }
+
+               /*  Look for merging possibilities  */
+               pNext = pNode->next_;
+               while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
+                       if (pNext->max_ > pNode->max_)
+                               pNode->max_ = pNext->max_;
+                       /*  Remove pNext, return ptr to pNext->next  */
+                       pNext = RemoveNode(pAS_Info, pNode, pNext);
+               }
+       }
+}
+
+/*
+ *  Reset all exclusion zones.
+ *  Add zones to protect the PLL FracN regions near zero
+ */
+static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+       u32 center;
+
+       dprintk(2, "\n");
+
+       pAS_Info->nZones = 0;   /*  this clears the used list  */
+       pAS_Info->usedZones = NULL;     /*  reset ptr                  */
+       pAS_Info->freeZones = NULL;     /*  reset ptr                  */
+
+       center =
+           pAS_Info->f_ref *
+           ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
+             pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
+       while (center <
+              pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
+              pAS_Info->f_LO1_FracN_Avoid) {
+               /*  Exclude LO1 FracN  */
+               MT2063_AddExclZone(pAS_Info,
+                                  center - pAS_Info->f_LO1_FracN_Avoid,
+                                  center - 1);
+               MT2063_AddExclZone(pAS_Info, center + 1,
+                                  center + pAS_Info->f_LO1_FracN_Avoid);
+               center += pAS_Info->f_ref;
+       }
+
+       center =
+           pAS_Info->f_ref *
+           ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
+             pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
+       while (center <
+              pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
+              pAS_Info->f_LO2_FracN_Avoid) {
+               /*  Exclude LO2 FracN  */
+               MT2063_AddExclZone(pAS_Info,
+                                  center - pAS_Info->f_LO2_FracN_Avoid,
+                                  center - 1);
+               MT2063_AddExclZone(pAS_Info, center + 1,
+                                  center + pAS_Info->f_LO2_FracN_Avoid);
+               center += pAS_Info->f_ref;
+       }
+
+       if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
+               /*  Exclude LO1 values that conflict with DECT channels */
+               MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
+               MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
+               MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
+               MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
+               MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
+       }
+
+       if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
+               MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
+               MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
+               MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
+               MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16  */
+               MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
+               MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
+               MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
+               MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
+               MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52  */
+               MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
+       }
+}
+
+/*
+ * MT_ChooseFirstIF - Choose the best available 1st IF
+ *                    If f_Desired is not excluded, choose that first.
+ *                    Otherwise, return the value closest to f_Center that is
+ *                    not excluded
+ */
+static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+       /*
+        * Update "f_Desired" to be the nearest "combinational-multiple" of
+        * "f_LO1_Step".
+        * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
+        * And F_LO1 is the arithmetic sum of f_in + f_Center.
+        * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
+        * However, the sum must be.
+        */
+       const u32 f_Desired =
+           pAS_Info->f_LO1_Step *
+           ((pAS_Info->f_if1_Request + pAS_Info->f_in +
+             pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
+           pAS_Info->f_in;
+       const u32 f_Step =
+           (pAS_Info->f_LO1_Step >
+            pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
+           f_LO2_Step;
+       u32 f_Center;
+       s32 i;
+       s32 j = 0;
+       u32 bDesiredExcluded = 0;
+       u32 bZeroExcluded = 0;
+       s32 tmpMin, tmpMax;
+       s32 bestDiff;
+       struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
+       struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
+
+       dprintk(2, "\n");
+
+       if (pAS_Info->nZones == 0)
+               return f_Desired;
+
+       /*
+        *  f_Center needs to be an integer multiple of f_Step away
+        *  from f_Desired
+        */
+       if (pAS_Info->f_if1_Center > f_Desired)
+               f_Center =
+                   f_Desired +
+                   f_Step *
+                   ((pAS_Info->f_if1_Center - f_Desired +
+                     f_Step / 2) / f_Step);
+       else
+               f_Center =
+                   f_Desired -
+                   f_Step *
+                   ((f_Desired - pAS_Info->f_if1_Center +
+                     f_Step / 2) / f_Step);
+
+       /*
+        * Take MT_ExclZones, center around f_Center and change the
+        * resolution to f_Step
+        */
+       while (pNode != NULL) {
+               /*  floor function  */
+               tmpMin =
+                   floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
+
+               /*  ceil function  */
+               tmpMax =
+                   ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
+
+               if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
+                       bDesiredExcluded = 1;
+
+               if ((tmpMin < 0) && (tmpMax > 0))
+                       bZeroExcluded = 1;
+
+               /*  See if this zone overlaps the previous  */
+               if ((j > 0) && (tmpMin < zones[j - 1].max_))
+                       zones[j - 1].max_ = tmpMax;
+               else {
+                       /*  Add new zone  */
+                       zones[j].min_ = tmpMin;
+                       zones[j].max_ = tmpMax;
+                       j++;
+               }
+               pNode = pNode->next_;
+       }
+
+       /*
+        *  If the desired is okay, return with it
+        */
+       if (bDesiredExcluded == 0)
+               return f_Desired;
+
+       /*
+        *  If the desired is excluded and the center is okay, return with it
+        */
+       if (bZeroExcluded == 0)
+               return f_Center;
+
+       /*  Find the value closest to 0 (f_Center)  */
+       bestDiff = zones[0].min_;
+       for (i = 0; i < j; i++) {
+               if (abs(zones[i].min_) < abs(bestDiff))
+                       bestDiff = zones[i].min_;
+               if (abs(zones[i].max_) < abs(bestDiff))
+                       bestDiff = zones[i].max_;
+       }
+
+       if (bestDiff < 0)
+               return f_Center - ((u32) (-bestDiff) * f_Step);
+
+       return f_Center + (bestDiff * f_Step);
+}
+
+/**
+ * gcd() - Uses Euclid's algorithm
+ *
+ * @u, @v:     Unsigned values whose GCD is desired.
+ *
+ * Returns THE greatest common divisor of u and v, if either value is 0,
+ * the other value is returned as the result.
+ */
+static u32 MT2063_gcd(u32 u, u32 v)
+{
+       u32 r;
+
+       while (v != 0) {
+               r = u % v;
+               u = v;
+               v = r;
+       }
+
+       return u;
+}
+
+/**
+ * IsSpurInBand() - Checks to see if a spur will be present within the IF's
+ *                  bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
+ *
+ *                    ma   mb                                     mc   md
+ *                  <--+-+-+-------------------+-------------------+-+-+-->
+ *                     |   ^                   0                   ^   |
+ *                     ^   b=-fIFOut+fIFBW/2      -b=+fIFOut-fIFBW/2   ^
+ *                     a=-fIFOut-fIFBW/2              -a=+fIFOut+fIFBW/2
+ *
+ *                  Note that some equations are doubled to prevent round-off
+ *                  problems when calculating fIFBW/2
+ *
+ * @pAS_Info:  Avoid Spurs information block
+ * @fm:                If spur, amount f_IF1 has to move negative
+ * @fp:                If spur, amount f_IF1 has to move positive
+ *
+ *  Returns 1 if an LO spur would be present, otherwise 0.
+ */
+static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
+                       u32 *fm, u32 * fp)
+{
+       /*
+        **  Calculate LO frequency settings.
+        */
+       u32 n, n0;
+       const u32 f_LO1 = pAS_Info->f_LO1;
+       const u32 f_LO2 = pAS_Info->f_LO2;
+       const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
+       const u32 c = d - pAS_Info->f_out_bw;
+       const u32 f = pAS_Info->f_zif_bw / 2;
+       const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
+       s32 f_nsLO1, f_nsLO2;
+       s32 f_Spur;
+       u32 ma, mb, mc, md, me, mf;
+       u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
+
+       dprintk(2, "\n");
+
+       *fm = 0;
+
+       /*
+        ** For each edge (d, c & f), calculate a scale, based on the gcd
+        ** of f_LO1, f_LO2 and the edge value.  Use the larger of this
+        ** gcd-based scale factor or f_Scale.
+        */
+       lo_gcd = MT2063_gcd(f_LO1, f_LO2);
+       gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
+       hgds = gd_Scale / 2;
+       gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
+       hgcs = gc_Scale / 2;
+       gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
+       hgfs = gf_Scale / 2;
+
+       n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
+
+       /*  Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic  */
+       for (n = n0; n <= pAS_Info->maxH1; ++n) {
+               md = (n * ((f_LO1 + hgds) / gd_Scale) -
+                     ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
+
+               /*  If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present  */
+               if (md >= pAS_Info->maxH1)
+                       break;
+
+               ma = (n * ((f_LO1 + hgds) / gd_Scale) +
+                     ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
+
+               /*  If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic  */
+               if (md == ma)
+                       continue;
+
+               mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
+                     ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
+               if (mc != md) {
+                       f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
+                       f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
+                       f_Spur =
+                           (gc_Scale * (f_nsLO1 - f_nsLO2)) +
+                           n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
+
+                       *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
+                       *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
+                       return 1;
+               }
+
+               /*  Location of Zero-IF-spur to be checked  */
+               me = (n * ((f_LO1 + hgfs) / gf_Scale) +
+                     ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
+               mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
+                     ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
+               if (me != mf) {
+                       f_nsLO1 = n * (f_LO1 / gf_Scale);
+                       f_nsLO2 = me * (f_LO2 / gf_Scale);
+                       f_Spur =
+                           (gf_Scale * (f_nsLO1 - f_nsLO2)) +
+                           n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
+
+                       *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
+                       *fm = (((s32) f - f_Spur) / (me - n)) + 1;
+                       return 1;
+               }
+
+               mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
+                     ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
+               if (ma != mb) {
+                       f_nsLO1 = n * (f_LO1 / gc_Scale);
+                       f_nsLO2 = ma * (f_LO2 / gc_Scale);
+                       f_Spur =
+                           (gc_Scale * (f_nsLO1 - f_nsLO2)) +
+                           n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
+
+                       *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
+                       *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
+                       return 1;
+               }
+       }
+
+       /*  No spurs found  */
+       return 0;
+}
+
+/*
+ * MT_AvoidSpurs() - Main entry point to avoid spurs.
+ *                   Checks for existing spurs in present LO1, LO2 freqs
+ *                   and if present, chooses spur-free LO1, LO2 combination
+ *                   that tunes the same input/output frequencies.
+ */
+static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+       u32 status = 0;
+       u32 fm, fp;             /*  restricted range on LO's        */
+       pAS_Info->bSpurAvoided = 0;
+       pAS_Info->nSpursFound = 0;
+
+       dprintk(2, "\n");
+
+       if (pAS_Info->maxH1 == 0)
+               return 0;
+
+       /*
+        * Avoid LO Generated Spurs
+        *
+        * Make sure that have no LO-related spurs within the IF output
+        * bandwidth.
+        *
+        * If there is an LO spur in this band, start at the current IF1 frequency
+        * and work out until we find a spur-free frequency or run up against the
+        * 1st IF SAW band edge.  Use temporary copies of fLO1 and fLO2 so that they
+        * will be unchanged if a spur-free setting is not found.
+        */
+       pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
+       if (pAS_Info->bSpurPresent) {
+               u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in;   /*  current attempt at a 1st IF  */
+               u32 zfLO1 = pAS_Info->f_LO1;    /*  current attempt at an LO1 freq  */
+               u32 zfLO2 = pAS_Info->f_LO2;    /*  current attempt at an LO2 freq  */
+               u32 delta_IF1;
+               u32 new_IF1;
+
+               /*
+                **  Spur was found, attempt to find a spur-free 1st IF
+                */
+               do {
+                       pAS_Info->nSpursFound++;
+
+                       /*  Raise f_IF1_upper, if needed  */
+                       MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
+
+                       /*  Choose next IF1 that is closest to f_IF1_CENTER              */
+                       new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
+
+                       if (new_IF1 > zfIF1) {
+                               pAS_Info->f_LO1 += (new_IF1 - zfIF1);
+                               pAS_Info->f_LO2 += (new_IF1 - zfIF1);
+                       } else {
+                               pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
+                               pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
+                       }
+                       zfIF1 = new_IF1;
+
+                       if (zfIF1 > pAS_Info->f_if1_Center)
+                               delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
+                       else
+                               delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
+
+                       pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
+               /*
+                *  Continue while the new 1st IF is still within the 1st IF bandwidth
+                *  and there is a spur in the band (again)
+                */
+               } while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
+
+               /*
+                * Use the LO-spur free values found.  If the search went all
+                * the way to the 1st IF band edge and always found spurs, just
+                * leave the original choice.  It's as "good" as any other.
+                */
+               if (pAS_Info->bSpurPresent == 1) {
+                       status |= MT2063_SPUR_PRESENT_ERR;
+                       pAS_Info->f_LO1 = zfLO1;
+                       pAS_Info->f_LO2 = zfLO2;
+               } else
+                       pAS_Info->bSpurAvoided = 1;
+       }
+
+       status |=
+           ((pAS_Info->
+             nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
+
+       return status;
+}
+
+/*
+ * Constants used by the tuning algorithm
+ */
+#define MT2063_REF_FREQ          (16000000UL)  /* Reference oscillator Frequency (in Hz) */
+#define MT2063_IF1_BW            (22000000UL)  /* The IF1 filter bandwidth (in Hz) */
+#define MT2063_TUNE_STEP_SIZE       (50000UL)  /* Tune in steps of 50 kHz */
+#define MT2063_SPUR_STEP_HZ        (250000UL)  /* Step size (in Hz) to move IF1 when avoiding spurs */
+#define MT2063_ZIF_BW             (2000000UL)  /* Zero-IF spur-free bandwidth (in Hz) */
+#define MT2063_MAX_HARMONICS_1         (15UL)  /* Highest intra-tuner LO Spur Harmonic to be avoided */
+#define MT2063_MAX_HARMONICS_2          (5UL)  /* Highest inter-tuner LO Spur Harmonic to be avoided */
+#define MT2063_MIN_LO_SEP         (1000000UL)  /* Minimum inter-tuner LO frequency separation */
+#define MT2063_LO1_FRACN_AVOID          (0UL)  /* LO1 FracN numerator avoid region (in Hz) */
+#define MT2063_LO2_FRACN_AVOID     (199999UL)  /* LO2 FracN numerator avoid region (in Hz) */
+#define MT2063_MIN_FIN_FREQ      (44000000UL)  /* Minimum input frequency (in Hz) */
+#define MT2063_MAX_FIN_FREQ    (1100000000UL)  /* Maximum input frequency (in Hz) */
+#define MT2063_MIN_FOUT_FREQ     (36000000UL)  /* Minimum output frequency (in Hz) */
+#define MT2063_MAX_FOUT_FREQ     (57000000UL)  /* Maximum output frequency (in Hz) */
+#define MT2063_MIN_DNC_FREQ    (1293000000UL)  /* Minimum LO2 frequency (in Hz) */
+#define MT2063_MAX_DNC_FREQ    (1614000000UL)  /* Maximum LO2 frequency (in Hz) */
+#define MT2063_MIN_UPC_FREQ    (1396000000UL)  /* Minimum LO1 frequency (in Hz) */
+#define MT2063_MAX_UPC_FREQ    (2750000000UL)  /* Maximum LO1 frequency (in Hz) */
+
+/*
+ *  Define the supported Part/Rev codes for the MT2063
+ */
+#define MT2063_B0       (0x9B)
+#define MT2063_B1       (0x9C)
+#define MT2063_B2       (0x9D)
+#define MT2063_B3       (0x9E)
+
+/**
+ * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
+ *
+ * @state:     struct mt2063_state pointer
+ *
+ * This function returns 0, if no lock, 1 if locked and a value < 1 if error
+ */
+static unsigned int mt2063_lockStatus(struct mt2063_state *state)
+{
+       const u32 nMaxWait = 100;       /*  wait a maximum of 100 msec   */
+       const u32 nPollRate = 2;        /*  poll status bits every 2 ms */
+       const u32 nMaxLoops = nMaxWait / nPollRate;
+       const u8 LO1LK = 0x80;
+       u8 LO2LK = 0x08;
+       u32 status;
+       u32 nDelays = 0;
+
+       dprintk(2, "\n");
+
+       /*  LO2 Lock bit was in a different place for B0 version  */
+       if (state->tuner_id == MT2063_B0)
+               LO2LK = 0x40;
+
+       do {
+               status = mt2063_read(state, MT2063_REG_LO_STATUS,
+                                    &state->reg[MT2063_REG_LO_STATUS], 1);
+
+               if (status < 0)
+                       return status;
+
+               if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
+                   (LO1LK | LO2LK)) {
+                       return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
+               }
+               msleep(nPollRate);      /*  Wait between retries  */
+       } while (++nDelays < nMaxLoops);
+
+       /*
+        * Got no lock or partial lock
+        */
+       return 0;
+}
+
+/*
+ *  Constants for setting receiver modes.
+ *  (6 modes defined at this time, enumerated by mt2063_delivery_sys)
+ *  (DNC1GC & DNC2GC are the values, which are used, when the specific
+ *   DNC Output is selected, the other is always off)
+ *
+ *                enum mt2063_delivery_sys
+ * -------------+----------------------------------------------
+ * Mode 0 :     | MT2063_CABLE_QAM
+ * Mode 1 :     | MT2063_CABLE_ANALOG
+ * Mode 2 :     | MT2063_OFFAIR_COFDM
+ * Mode 3 :     | MT2063_OFFAIR_COFDM_SAWLESS
+ * Mode 4 :     | MT2063_OFFAIR_ANALOG
+ * Mode 5 :     | MT2063_OFFAIR_8VSB
+ * --------------+----------------------------------------------
+ *
+ *                |<----------   Mode  -------------->|
+ *    Reg Field   |  0  |  1  |  2  |  3  |  4  |  5  |
+ *    ------------+-----+-----+-----+-----+-----+-----+
+ *    RFAGCen     | OFF | OFF | OFF | OFF | OFF | OFF
+ *    LNARin      |   0 |   0 |   3 |   3 |  3  |  3
+ *    FIFFQen     |   1 |   1 |   1 |   1 |  1  |  1
+ *    FIFFq       |   0 |   0 |   0 |   0 |  0  |  0
+ *    DNC1gc      |   0 |   0 |   0 |   0 |  0  |  0
+ *    DNC2gc      |   0 |   0 |   0 |   0 |  0  |  0
+ *    GCU Auto    |   1 |   1 |   1 |   1 |  1  |  1
+ *    LNA max Atn |  31 |  31 |  31 |  31 | 31  | 31
+ *    LNA Target  |  44 |  43 |  43 |  43 | 43  | 43
+ *    ign  RF Ovl |   0 |   0 |   0 |   0 |  0  |  0
+ *    RF  max Atn |  31 |  31 |  31 |  31 | 31  | 31
+ *    PD1 Target  |  36 |  36 |  38 |  38 | 36  | 38
+ *    ign FIF Ovl |   0 |   0 |   0 |   0 |  0  |  0
+ *    FIF max Atn |   5 |   5 |   5 |   5 |  5  |  5
+ *    PD2 Target  |  40 |  33 |  42 |  42 | 33  | 42
+ */
+
+enum mt2063_delivery_sys {
+       MT2063_CABLE_QAM = 0,
+       MT2063_CABLE_ANALOG,
+       MT2063_OFFAIR_COFDM,
+       MT2063_OFFAIR_COFDM_SAWLESS,
+       MT2063_OFFAIR_ANALOG,
+       MT2063_OFFAIR_8VSB,
+       MT2063_NUM_RCVR_MODES
+};
+
+static const char *mt2063_mode_name[] = {
+       [MT2063_CABLE_QAM]              = "digital cable",
+       [MT2063_CABLE_ANALOG]           = "analog cable",
+       [MT2063_OFFAIR_COFDM]           = "digital offair",
+       [MT2063_OFFAIR_COFDM_SAWLESS]   = "digital offair without SAW",
+       [MT2063_OFFAIR_ANALOG]          = "analog offair",
+       [MT2063_OFFAIR_8VSB]            = "analog offair 8vsb",
+};
+
+static const u8 RFAGCEN[]      = {  0,  0,  0,  0,  0,  0 };
+static const u8 LNARIN[]       = {  0,  0,  3,  3,  3,  3 };
+static const u8 FIFFQEN[]      = {  1,  1,  1,  1,  1,  1 };
+static const u8 FIFFQ[]                = {  0,  0,  0,  0,  0,  0 };
+static const u8 DNC1GC[]       = {  0,  0,  0,  0,  0,  0 };
+static const u8 DNC2GC[]       = {  0,  0,  0,  0,  0,  0 };
+static const u8 ACLNAMAX[]     = { 31, 31, 31, 31, 31, 31 };
+static const u8 LNATGT[]       = { 44, 43, 43, 43, 43, 43 };
+static const u8 RFOVDIS[]      = {  0,  0,  0,  0,  0,  0 };
+static const u8 ACRFMAX[]      = { 31, 31, 31, 31, 31, 31 };
+static const u8 PD1TGT[]       = { 36, 36, 38, 38, 36, 38 };
+static const u8 FIFOVDIS[]     = {  0,  0,  0,  0,  0,  0 };
+static const u8 ACFIFMAX[]     = { 29, 29, 29, 29, 29, 29 };
+static const u8 PD2TGT[]       = { 40, 33, 38, 42, 30, 38 };
+
+/*
+ * mt2063_set_dnc_output_enable()
+ */
+static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
+                                       enum MT2063_DNC_Output_Enable *pValue)
+{
+       dprintk(2, "\n");
+
+       if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
+               if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
+                       *pValue = MT2063_DNC_NONE;
+               else
+                       *pValue = MT2063_DNC_2;
+       } else {        /* DNC1 is on */
+               if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
+                       *pValue = MT2063_DNC_1;
+               else
+                       *pValue = MT2063_DNC_BOTH;
+       }
+       return 0;
+}
+
+/*
+ * mt2063_set_dnc_output_enable()
+ */
+static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
+                                       enum MT2063_DNC_Output_Enable nValue)
+{
+       u32 status = 0; /* Status to be returned        */
+       u8 val = 0;
+
+       dprintk(2, "\n");
+
+       /* selects, which DNC output is used */
+       switch (nValue) {
+       case MT2063_DNC_NONE:
+               val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
+               if (state->reg[MT2063_REG_DNC_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_DNC_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
+               if (state->reg[MT2063_REG_VGA_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_VGA_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
+               if (state->reg[MT2063_REG_RSVD_20] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_RSVD_20,
+                                         val);
+
+               break;
+       case MT2063_DNC_1:
+               val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);     /* Set DNC1GC=x */
+               if (state->reg[MT2063_REG_DNC_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_DNC_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
+               if (state->reg[MT2063_REG_VGA_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_VGA_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
+               if (state->reg[MT2063_REG_RSVD_20] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_RSVD_20,
+                                         val);
+
+               break;
+       case MT2063_DNC_2:
+               val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
+               if (state->reg[MT2063_REG_DNC_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_DNC_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);     /* Set DNC2GC=x */
+               if (state->reg[MT2063_REG_VGA_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_VGA_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
+               if (state->reg[MT2063_REG_RSVD_20] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_RSVD_20,
+                                         val);
+
+               break;
+       case MT2063_DNC_BOTH:
+               val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);     /* Set DNC1GC=x */
+               if (state->reg[MT2063_REG_DNC_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_DNC_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);     /* Set DNC2GC=x */
+               if (state->reg[MT2063_REG_VGA_GAIN] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_VGA_GAIN,
+                                         val);
+
+               val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
+               if (state->reg[MT2063_REG_RSVD_20] !=
+                   val)
+                       status |=
+                           mt2063_setreg(state,
+                                         MT2063_REG_RSVD_20,
+                                         val);
+
+               break;
+       default:
+               break;
+       }
+
+       return status;
+}
+
+/*
+ * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
+ *                           the selected enum mt2063_delivery_sys type.
+ *
+ *  (DNC1GC & DNC2GC are the values, which are used, when the specific
+ *   DNC Output is selected, the other is always off)
+ *
+ * @state:     ptr to mt2063_state structure
+ * @Mode:      desired reciever delivery system
+ *
+ * Note: Register cache must be valid for it to work
+ */
+
+static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
+                                 enum mt2063_delivery_sys Mode)
+{
+       u32 status = 0; /* Status to be returned        */
+       u8 val;
+       u32 longval;
+
+       dprintk(2, "\n");
+
+       if (Mode >= MT2063_NUM_RCVR_MODES)
+               status = -ERANGE;
+
+       /* RFAGCen */
+       if (status >= 0) {
+               val =
+                   (state->
+                    reg[MT2063_REG_PD1_TGT] & (u8) ~0x40) | (RFAGCEN[Mode]
+                                                                  ? 0x40 :
+                                                                  0x00);
+               if (state->reg[MT2063_REG_PD1_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+       }
+
+       /* LNARin */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_CTRL_2C] & (u8) ~0x03) |
+                        (LNARIN[Mode] & 0x03);
+               if (state->reg[MT2063_REG_CTRL_2C] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
+       }
+
+       /* FIFFQEN and FIFFQ */
+       if (status >= 0) {
+               val =
+                   (state->
+                    reg[MT2063_REG_FIFF_CTRL2] & (u8) ~0xF0) |
+                   (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
+               if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
+                       status |=
+                           mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
+                       /* trigger FIFF calibration, needed after changing FIFFQ */
+                       val =
+                           (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
+                       status |=
+                           mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
+                       val =
+                           (state->
+                            reg[MT2063_REG_FIFF_CTRL] & (u8) ~0x01);
+                       status |=
+                           mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
+               }
+       }
+
+       /* DNC1GC & DNC2GC */
+       status |= mt2063_get_dnc_output_enable(state, &longval);
+       status |= mt2063_set_dnc_output_enable(state, longval);
+
+       /* acLNAmax */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_LNA_OV] & (u8) ~0x1F) |
+                        (ACLNAMAX[Mode] & 0x1F);
+               if (state->reg[MT2063_REG_LNA_OV] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
+       }
+
+       /* LNATGT */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x3F) |
+                        (LNATGT[Mode] & 0x3F);
+               if (state->reg[MT2063_REG_LNA_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
+       }
+
+       /* ACRF */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_RF_OV] & (u8) ~0x1F) |
+                        (ACRFMAX[Mode] & 0x1F);
+               if (state->reg[MT2063_REG_RF_OV] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
+       }
+
+       /* PD1TGT */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x3F) |
+                        (PD1TGT[Mode] & 0x3F);
+               if (state->reg[MT2063_REG_PD1_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+       }
+
+       /* FIFATN */
+       if (status >= 0) {
+               u8 val = ACFIFMAX[Mode];
+               if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
+                       val = 5;
+               val = (state->reg[MT2063_REG_FIF_OV] & (u8) ~0x1F) |
+                     (val & 0x1F);
+               if (state->reg[MT2063_REG_FIF_OV] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
+       }
+
+       /* PD2TGT */
+       if (status >= 0) {
+               u8 val = (state->reg[MT2063_REG_PD2_TGT] & (u8) ~0x3F) |
+                   (PD2TGT[Mode] & 0x3F);
+               if (state->reg[MT2063_REG_PD2_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
+       }
+
+       /* Ignore ATN Overload */
+       if (status >= 0) {
+               val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x80) |
+                     (RFOVDIS[Mode] ? 0x80 : 0x00);
+               if (state->reg[MT2063_REG_LNA_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
+       }
+
+       /* Ignore FIF Overload */
+       if (status >= 0) {
+               val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x80) |
+                     (FIFOVDIS[Mode] ? 0x80 : 0x00);
+               if (state->reg[MT2063_REG_PD1_TGT] != val)
+                       status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+       }
+
+       if (status >= 0) {
+               state->rcvr_mode = Mode;
+               dprintk(1, "mt2063 mode changed to %s\n",
+                       mt2063_mode_name[state->rcvr_mode]);
+       }
+
+       return status;
+}
+
+/*
+ * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
+ *                               sections of the MT2063
+ *
+ * @Bits:              Mask bits to be cleared.
+ *
+ * See definition of MT2063_Mask_Bits type for description
+ * of each of the power bits.
+ */
+static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
+                                    enum MT2063_Mask_Bits Bits)
+{
+       u32 status = 0;
+
+       dprintk(2, "\n");
+       Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);   /* Only valid bits for this tuner */
+       if ((Bits & 0xFF00) != 0) {
+               state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
+               status |=
+                   mt2063_write(state,
+                                   MT2063_REG_PWR_2,
+                                   &state->reg[MT2063_REG_PWR_2], 1);
+       }
+       if ((Bits & 0xFF) != 0) {
+               state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
+               status |=
+                   mt2063_write(state,
+                                   MT2063_REG_PWR_1,
+                                   &state->reg[MT2063_REG_PWR_1], 1);
+       }
+
+       return status;
+}
+
+/*
+ * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
+ *                            When Shutdown is 1, any section whose power
+ *                            mask is set will be shutdown.
+ */
+static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
+{
+       u32 status;
+
+       dprintk(2, "\n");
+       if (Shutdown == 1)
+               state->reg[MT2063_REG_PWR_1] |= 0x04;
+       else
+               state->reg[MT2063_REG_PWR_1] &= ~0x04;
+
+       status = mt2063_write(state,
+                           MT2063_REG_PWR_1,
+                           &state->reg[MT2063_REG_PWR_1], 1);
+
+       if (Shutdown != 1) {
+               state->reg[MT2063_REG_BYP_CTRL] =
+                   (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
+               status |=
+                   mt2063_write(state,
+                                   MT2063_REG_BYP_CTRL,
+                                   &state->reg[MT2063_REG_BYP_CTRL],
+                                   1);
+               state->reg[MT2063_REG_BYP_CTRL] =
+                   (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
+               status |=
+                   mt2063_write(state,
+                                   MT2063_REG_BYP_CTRL,
+                                   &state->reg[MT2063_REG_BYP_CTRL],
+                                   1);
+       }
+
+       return status;
+}
+
+static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
+{
+       return f_ref * (f_LO / f_ref)
+           + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
+}
+
+/**
+ * fLO_FractionalTerm() - Calculates the portion contributed by FracN / denom.
+ *                        This function preserves maximum precision without
+ *                        risk of overflow.  It accurately calculates
+ *                        f_ref * num / denom to within 1 HZ with fixed math.
+ *
+ * @num :      Fractional portion of the multiplier
+ * @denom:     denominator portion of the ratio
+ * @f_Ref:     SRO frequency.
+ *
+ * This calculation handles f_ref as two separate 14-bit fields.
+ * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
+ * This is the genesis of the magic number "14" and the magic mask value of
+ * 0x03FFF.
+ *
+ * This routine successfully handles denom values up to and including 2^18.
+ *  Returns:        f_ref * num / denom
+ */
+static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
+{
+       u32 t1 = (f_ref >> 14) * num;
+       u32 term1 = t1 / denom;
+       u32 loss = t1 % denom;
+       u32 term2 =
+           (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
+       return (term1 << 14) + term2;
+}
+
+/*
+ * CalcLO1Mult()- Calculates Integer divider value and the numerator
+ *                value for a FracN PLL.
+ *
+ *                This function assumes that the f_LO and f_Ref are
+ *                evenly divisible by f_LO_Step.
+ *
+ * @Div:       OUTPUT: Whole number portion of the multiplier
+ * @FracN:     OUTPUT: Fractional portion of the multiplier
+ * @f_LO:      desired LO frequency.
+ * @f_LO_Step: Minimum step size for the LO (in Hz).
+ * @f_Ref:     SRO frequency.
+ * @f_Avoid:   Range of PLL frequencies to avoid near integer multiples
+ *             of f_Ref (in Hz).
+ *
+ * Returns:        Recalculated LO frequency.
+ */
+static u32 MT2063_CalcLO1Mult(u32 *Div,
+                             u32 *FracN,
+                             u32 f_LO,
+                             u32 f_LO_Step, u32 f_Ref)
+{
+       /*  Calculate the whole number portion of the divider */
+       *Div = f_LO / f_Ref;
+
+       /*  Calculate the numerator value (round to nearest f_LO_Step) */
+       *FracN =
+           (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
+            (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
+
+       return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
+}
+
+/**
+ * CalcLO2Mult() - Calculates Integer divider value and the numerator
+ *                 value for a FracN PLL.
+ *
+ *                  This function assumes that the f_LO and f_Ref are
+ *                  evenly divisible by f_LO_Step.
+ *
+ * @Div:       OUTPUT: Whole number portion of the multiplier
+ * @FracN:     OUTPUT: Fractional portion of the multiplier
+ * @f_LO:      desired LO frequency.
+ * @f_LO_Step: Minimum step size for the LO (in Hz).
+ * @f_Ref:     SRO frequency.
+ * @f_Avoid:   Range of PLL frequencies to avoid near
+ *             integer multiples of f_Ref (in Hz).
+ *
+ * Returns: Recalculated LO frequency.
+ */
+static u32 MT2063_CalcLO2Mult(u32 *Div,
+                             u32 *FracN,
+                             u32 f_LO,
+                             u32 f_LO_Step, u32 f_Ref)
+{
+       /*  Calculate the whole number portion of the divider */
+       *Div = f_LO / f_Ref;
+
+       /*  Calculate the numerator value (round to nearest f_LO_Step) */
+       *FracN =
+           (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
+            (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
+
+       return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
+                                                           8191);
+}
+
+/*
+ * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
+ *                        used for a given input frequency.
+ *
+ * @state:     ptr to tuner data structure
+ * @f_in:      RF input center frequency (in Hz).
+ *
+ * Returns: ClearTune filter number (0-31)
+ */
+static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
+{
+       u32 RFBand;
+       u32 idx;                /*  index loop                      */
+
+       /*
+        **  Find RF Band setting
+        */
+       RFBand = 31;            /*  def when f_in > all    */
+       for (idx = 0; idx < 31; ++idx) {
+               if (state->CTFiltMax[idx] >= f_in) {
+                       RFBand = idx;
+                       break;
+               }
+       }
+       return RFBand;
+}
+
+/*
+ * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
+ */
+static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
+{                              /* RF input center frequency   */
+
+       u32 status = 0;
+       u32 LO1;                /*  1st LO register value           */
+       u32 Num1;               /*  Numerator for LO1 reg. value    */
+       u32 f_IF1;              /*  1st IF requested                */
+       u32 LO2;                /*  2nd LO register value           */
+       u32 Num2;               /*  Numerator for LO2 reg. value    */
+       u32 ofLO1, ofLO2;       /*  last time's LO frequencies      */
+       u8 fiffc = 0x80;        /*  FIFF center freq from tuner     */
+       u32 fiffof;             /*  Offset from FIFF center freq    */
+       const u8 LO1LK = 0x80;  /*  Mask for LO1 Lock bit           */
+       u8 LO2LK = 0x08;        /*  Mask for LO2 Lock bit           */
+       u8 val;
+       u32 RFBand;
+
+       dprintk(2, "\n");
+       /*  Check the input and output frequency ranges                   */
+       if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
+               return -EINVAL;
+
+       if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
+           || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
+               return -EINVAL;
+
+       /*
+        * Save original LO1 and LO2 register values
+        */
+       ofLO1 = state->AS_Data.f_LO1;
+       ofLO2 = state->AS_Data.f_LO2; 
+
+       /*
+        * Find and set RF Band setting
+        */
+       if (state->ctfilt_sw == 1) {
+               val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
+               if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
+                       status |=
+                           mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
+               }
+               val = state->reg[MT2063_REG_CTUNE_OV];
+               RFBand = FindClearTuneFilter(state, f_in);
+               state->reg[MT2063_REG_CTUNE_OV] =
+                   (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
+                             | RFBand);
+               if (state->reg[MT2063_REG_CTUNE_OV] != val) {
+                       status |=
+                           mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
+               }
+       }
+
+       /*
+        * Read the FIFF Center Frequency from the tuner
+        */
+       if (status >= 0) {
+               status |=
+                   mt2063_read(state,
+                                  MT2063_REG_FIFFC,
+                                  &state->reg[MT2063_REG_FIFFC], 1);
+               fiffc = state->reg[MT2063_REG_FIFFC];
+       }
+       /*
+        * Assign in the requested values
+        */
+       state->AS_Data.f_in = f_in;
+       /*  Request a 1st IF such that LO1 is on a step size */
+       state->AS_Data.f_if1_Request =
+           MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
+                            state->AS_Data.f_LO1_Step,
+                            state->AS_Data.f_ref) - f_in;
+
+       /*
+        * Calculate frequency settings.  f_IF1_FREQ + f_in is the
+        * desired LO1 frequency
+        */
+       MT2063_ResetExclZones(&state->AS_Data);
+
+       f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
+
+       state->AS_Data.f_LO1 =
+           MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
+                            state->AS_Data.f_ref);
+
+       state->AS_Data.f_LO2 =
+           MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
+                            state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+
+       /*
+        * Check for any LO spurs in the output bandwidth and adjust
+        * the LO settings to avoid them if needed
+        */
+       status |= MT2063_AvoidSpurs(&state->AS_Data);
+       /*
+        * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
+        * Recalculate the LO frequencies and the values to be placed
+        * in the tuning registers.
+        */
+       state->AS_Data.f_LO1 =
+           MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
+                              state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
+       state->AS_Data.f_LO2 =
+           MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
+                            state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+       state->AS_Data.f_LO2 =
+           MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
+                              state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+
+       /*
+        *  Check the upconverter and downconverter frequency ranges
+        */
+       if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
+           || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
+               status |= MT2063_UPC_RANGE;
+       if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
+           || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
+               status |= MT2063_DNC_RANGE;
+       /*  LO2 Lock bit was in a different place for B0 version  */
+       if (state->tuner_id == MT2063_B0)
+               LO2LK = 0x40;
+
+       /*
+        *  If we have the same LO frequencies and we're already locked,
+        *  then skip re-programming the LO registers.
+        */
+       if ((ofLO1 != state->AS_Data.f_LO1)
+           || (ofLO2 != state->AS_Data.f_LO2)
+           || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
+               (LO1LK | LO2LK))) {
+               /*
+                * Calculate the FIFFOF register value
+                *
+                *           IF1_Actual
+                * FIFFOF = ------------ - 8 * FIFFC - 4992
+                *            f_ref/64
+                */
+               fiffof =
+                   (state->AS_Data.f_LO1 -
+                    f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
+                   4992;
+               if (fiffof > 0xFF)
+                       fiffof = 0xFF;
+
+               /*
+                * Place all of the calculated values into the local tuner
+                * register fields.
+                */
+               if (status >= 0) {
+                       state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF);     /* DIV1q */
+                       state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);    /* NUM1q */
+                       state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1)      /* DIV2q */
+                                                                  |(Num2 >> 12));      /* NUM2q (hi) */
+                       state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4);   /* NUM2q (mid) */
+                       state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
+
+                       /*
+                        * Now write out the computed register values
+                        * IMPORTANT: There is a required order for writing
+                        *            (0x05 must follow all the others).
+                        */
+                       status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5);  /* 0x01 - 0x05 */
+                       if (state->tuner_id == MT2063_B0) {
+                               /* Re-write the one-shot bits to trigger the tune operation */
+                               status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1);  /* 0x05 */
+                       }
+                       /* Write out the FIFF offset only if it's changing */
+                       if (state->reg[MT2063_REG_FIFF_OFFSET] !=
+                           (u8) fiffof) {
+                               state->reg[MT2063_REG_FIFF_OFFSET] =
+                                   (u8) fiffof;
+                               status |=
+                                   mt2063_write(state,
+                                                   MT2063_REG_FIFF_OFFSET,
+                                                   &state->
+                                                   reg[MT2063_REG_FIFF_OFFSET],
+                                                   1);
+                       }
+               }
+
+               /*
+                * Check for LO's locking
+                */
+
+               if (status < 0)
+                       return status;
+
+               status = mt2063_lockStatus(state);
+               if (status < 0)
+                       return status;
+               if (!status)
+                       return -EINVAL;         /* Couldn't lock */
+
+               /*
+                * If we locked OK, assign calculated data to mt2063_state structure
+                */
+               state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
+       }
+
+       return status;
+}
+
+static const u8 MT2063B0_defaults[] = {
+       /* Reg,  Value */
+       0x19, 0x05,
+       0x1B, 0x1D,
+       0x1C, 0x1F,
+       0x1D, 0x0F,
+       0x1E, 0x3F,
+       0x1F, 0x0F,
+       0x20, 0x3F,
+       0x22, 0x21,
+       0x23, 0x3F,
+       0x24, 0x20,
+       0x25, 0x3F,
+       0x27, 0xEE,
+       0x2C, 0x27,     /*  bit at 0x20 is cleared below  */
+       0x30, 0x03,
+       0x2C, 0x07,     /*  bit at 0x20 is cleared here   */
+       0x2D, 0x87,
+       0x2E, 0xAA,
+       0x28, 0xE1,     /*  Set the FIFCrst bit here      */
+       0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
+       0x00
+};
+
+/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
+static const u8 MT2063B1_defaults[] = {
+       /* Reg,  Value */
+       0x05, 0xF0,
+       0x11, 0x10,     /* New Enable AFCsd */
+       0x19, 0x05,
+       0x1A, 0x6C,
+       0x1B, 0x24,
+       0x1C, 0x28,
+       0x1D, 0x8F,
+       0x1E, 0x14,
+       0x1F, 0x8F,
+       0x20, 0x57,
+       0x22, 0x21,     /* New - ver 1.03 */
+       0x23, 0x3C,     /* New - ver 1.10 */
+       0x24, 0x20,     /* New - ver 1.03 */
+       0x2C, 0x24,     /*  bit at 0x20 is cleared below  */
+       0x2D, 0x87,     /*  FIFFQ=0  */
+       0x2F, 0xF3,
+       0x30, 0x0C,     /* New - ver 1.11 */
+       0x31, 0x1B,     /* New - ver 1.11 */
+       0x2C, 0x04,     /*  bit at 0x20 is cleared here  */
+       0x28, 0xE1,     /*  Set the FIFCrst bit here      */
+       0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
+       0x00
+};
+
+/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
+static const u8 MT2063B3_defaults[] = {
+       /* Reg,  Value */
+       0x05, 0xF0,
+       0x19, 0x3D,
+       0x2C, 0x24,     /*  bit at 0x20 is cleared below  */
+       0x2C, 0x04,     /*  bit at 0x20 is cleared here  */
+       0x28, 0xE1,     /*  Set the FIFCrst bit here      */
+       0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
+       0x00
+};
+
+static int mt2063_init(struct dvb_frontend *fe)
+{
+       u32 status;
+       struct mt2063_state *state = fe->tuner_priv;
+       u8 all_resets = 0xF0;   /* reset/load bits */
+       const u8 *def = NULL;
+       char *step;
+       u32 FCRUN;
+       s32 maxReads;
+       u32 fcu_osc;
+       u32 i;
+
+       dprintk(2, "\n");
+
+       state->rcvr_mode = MT2063_CABLE_QAM;
+
+       /*  Read the Part/Rev code from the tuner */
+       status = mt2063_read(state, MT2063_REG_PART_REV,
+                            &state->reg[MT2063_REG_PART_REV], 1);
+       if (status < 0) {
+               printk(KERN_ERR "Can't read mt2063 part ID\n");
+               return status;
+       }
+
+       /* Check the part/rev code */
+       switch (state->reg[MT2063_REG_PART_REV]) {
+       case MT2063_B0:
+               step = "B0";
+               break;
+       case MT2063_B1:
+               step = "B1";
+               break;
+       case MT2063_B2:
+               step = "B2";
+               break;
+       case MT2063_B3:
+               step = "B3";
+               break;
+       default:
+               printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
+                      state->reg[MT2063_REG_PART_REV]);
+               return -ENODEV; /*  Wrong tuner Part/Rev code */
+       }
+
+       /*  Check the 2nd byte of the Part/Rev code from the tuner */
+       status = mt2063_read(state, MT2063_REG_RSVD_3B,
+                            &state->reg[MT2063_REG_RSVD_3B], 1);
+
+       /* b7 != 0 ==> NOT MT2063 */
+       if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
+               printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
+                      state->reg[MT2063_REG_PART_REV],
+                      state->reg[MT2063_REG_RSVD_3B]);
+               return -ENODEV; /*  Wrong tuner Part/Rev code */
+       }
+
+       printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
+
+       /*  Reset the tuner  */
+       status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
+       if (status < 0)
+               return status;
+
+       /* change all of the default values that vary from the HW reset values */
+       /*  def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
+       switch (state->reg[MT2063_REG_PART_REV]) {
+       case MT2063_B3:
+               def = MT2063B3_defaults;
+               break;
+
+       case MT2063_B1:
+               def = MT2063B1_defaults;
+               break;
+
+       case MT2063_B0:
+               def = MT2063B0_defaults;
+               break;
+
+       default:
+               return -ENODEV;
+               break;
+       }
+
+       while (status >= 0 && *def) {
+               u8 reg = *def++;
+               u8 val = *def++;
+               status = mt2063_write(state, reg, &val, 1);
+       }
+       if (status < 0)
+               return status;
+
+       /*  Wait for FIFF location to complete.  */
+       FCRUN = 1;
+       maxReads = 10;
+       while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
+               msleep(2);
+               status = mt2063_read(state,
+                                        MT2063_REG_XO_STATUS,
+                                        &state->
+                                        reg[MT2063_REG_XO_STATUS], 1);
+               FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
+       }
+
+       if (FCRUN != 0 || status < 0)
+               return -ENODEV;
+
+       status = mt2063_read(state,
+                          MT2063_REG_FIFFC,
+                          &state->reg[MT2063_REG_FIFFC], 1);
+       if (status < 0)
+               return status;
+
+       /* Read back all the registers from the tuner */
+       status = mt2063_read(state,
+                               MT2063_REG_PART_REV,
+                               state->reg, MT2063_REG_END_REGS);
+       if (status < 0)
+               return status;
+
+       /*  Initialize the tuner state.  */
+       state->tuner_id = state->reg[MT2063_REG_PART_REV];
+       state->AS_Data.f_ref = MT2063_REF_FREQ;
+       state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
+                                     ((u32) state->reg[MT2063_REG_FIFFC] + 640);
+       state->AS_Data.f_if1_bw = MT2063_IF1_BW;
+       state->AS_Data.f_out = 43750000UL;
+       state->AS_Data.f_out_bw = 6750000UL;
+       state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
+       state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
+       state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
+       state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
+       state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
+       state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
+       state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
+       state->AS_Data.f_LO1 = 2181000000UL;
+       state->AS_Data.f_LO2 = 1486249786UL;
+       state->f_IF1_actual = state->AS_Data.f_if1_Center;
+       state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
+       state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
+       state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
+       state->num_regs = MT2063_REG_END_REGS;
+       state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
+       state->ctfilt_sw = 0;
+
+       state->CTFiltMax[0] = 69230000;
+       state->CTFiltMax[1] = 105770000;
+       state->CTFiltMax[2] = 140350000;
+       state->CTFiltMax[3] = 177110000;
+       state->CTFiltMax[4] = 212860000;
+       state->CTFiltMax[5] = 241130000;
+       state->CTFiltMax[6] = 274370000;
+       state->CTFiltMax[7] = 309820000;
+       state->CTFiltMax[8] = 342450000;
+       state->CTFiltMax[9] = 378870000;
+       state->CTFiltMax[10] = 416210000;
+       state->CTFiltMax[11] = 456500000;
+       state->CTFiltMax[12] = 495790000;
+       state->CTFiltMax[13] = 534530000;
+       state->CTFiltMax[14] = 572610000;
+       state->CTFiltMax[15] = 598970000;
+       state->CTFiltMax[16] = 635910000;
+       state->CTFiltMax[17] = 672130000;
+       state->CTFiltMax[18] = 714840000;
+       state->CTFiltMax[19] = 739660000;
+       state->CTFiltMax[20] = 770410000;
+       state->CTFiltMax[21] = 814660000;
+       state->CTFiltMax[22] = 846950000;
+       state->CTFiltMax[23] = 867820000;
+       state->CTFiltMax[24] = 915980000;
+       state->CTFiltMax[25] = 947450000;
+       state->CTFiltMax[26] = 983110000;
+       state->CTFiltMax[27] = 1021630000;
+       state->CTFiltMax[28] = 1061870000;
+       state->CTFiltMax[29] = 1098330000;
+       state->CTFiltMax[30] = 1138990000;
+
+       /*
+        **   Fetch the FCU osc value and use it and the fRef value to
+        **   scale all of the Band Max values
+        */
+
+       state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
+       status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
+                             &state->reg[MT2063_REG_CTUNE_CTRL], 1);
+       if (status < 0)
+               return status;
+
+       /*  Read the ClearTune filter calibration value  */
+       status = mt2063_read(state, MT2063_REG_FIFFC,
+                            &state->reg[MT2063_REG_FIFFC], 1);
+       if (status < 0)
+               return status;
+
+       fcu_osc = state->reg[MT2063_REG_FIFFC];
+
+       state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
+       status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
+                             &state->reg[MT2063_REG_CTUNE_CTRL], 1);
+       if (status < 0)
+               return status;
+
+       /*  Adjust each of the values in the ClearTune filter cross-over table  */
+       for (i = 0; i < 31; i++)
+               state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
+
+       status = MT2063_SoftwareShutdown(state, 1);
+       if (status < 0)
+               return status;
+       status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
+       if (status < 0)
+               return status;
+
+       state->init = true;
+
+       return 0;
+}
+
+static int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+       int status;
+
+       dprintk(2, "\n");
+
+       if (!state->init)
+               return -ENODEV;
+
+       *tuner_status = 0;
+       status = mt2063_lockStatus(state);
+       if (status < 0)
+               return status;
+       if (status)
+               *tuner_status = TUNER_STATUS_LOCKED;
+
+       dprintk(1, "Tuner status: %d", *tuner_status);
+
+       return 0;
+}
+
+static int mt2063_release(struct dvb_frontend *fe)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+
+       dprintk(2, "\n");
+
+       fe->tuner_priv = NULL;
+       kfree(state);
+
+       return 0;
+}
+
+static int mt2063_set_analog_params(struct dvb_frontend *fe,
+                                   struct analog_parameters *params)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+       s32 pict_car;
+       s32 pict2chanb_vsb;
+       s32 ch_bw;
+       s32 if_mid;
+       s32 rcvr_mode;
+       int status;
+
+       dprintk(2, "\n");
+
+       if (!state->init) {
+               status = mt2063_init(fe);
+               if (status < 0)
+                       return status;
+       }
+
+       switch (params->mode) {
+       case V4L2_TUNER_RADIO:
+               pict_car = 38900000;
+               ch_bw = 8000000;
+               pict2chanb_vsb = -(ch_bw / 2);
+               rcvr_mode = MT2063_OFFAIR_ANALOG;
+               break;
+       case V4L2_TUNER_ANALOG_TV:
+               rcvr_mode = MT2063_CABLE_ANALOG;
+               if (params->std & ~V4L2_STD_MN) {
+                       pict_car = 38900000;
+                       ch_bw = 6000000;
+                       pict2chanb_vsb = -1250000;
+               } else if (params->std & V4L2_STD_PAL_G) {
+                       pict_car = 38900000;
+                       ch_bw = 7000000;
+                       pict2chanb_vsb = -1250000;
+               } else {                /* PAL/SECAM standards */
+                       pict_car = 38900000;
+                       ch_bw = 8000000;
+                       pict2chanb_vsb = -1250000;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
+
+       state->AS_Data.f_LO2_Step = 125000;     /* FIXME: probably 5000 for FM */
+       state->AS_Data.f_out = if_mid;
+       state->AS_Data.f_out_bw = ch_bw + 750000;
+       status = MT2063_SetReceiverMode(state, rcvr_mode);
+       if (status < 0)
+               return status;
+
+       dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
+               params->frequency, ch_bw, pict2chanb_vsb);
+
+       status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
+       if (status < 0)
+               return status;
+
+       state->frequency = params->frequency;
+       return 0;
+}
+
+/*
+ * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
+ * So, the amount of the needed bandwith is given by:
+ *     Bw = Symbol_rate * (1 + 0.15)
+ * As such, the maximum symbol rate supported by 6 MHz is given by:
+ *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
+ */
+#define MAX_SYMBOL_RATE_6MHz   5217391
+
+static int mt2063_set_params(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct mt2063_state *state = fe->tuner_priv;
+       int status;
+       s32 pict_car;
+       s32 pict2chanb_vsb;
+       s32 ch_bw;
+       s32 if_mid;
+       s32 rcvr_mode;
+
+       if (!state->init) {
+               status = mt2063_init(fe);
+               if (status < 0)
+                       return status;
+       }
+
+       dprintk(2, "\n");
+
+       if (c->bandwidth_hz == 0)
+               return -EINVAL;
+       if (c->bandwidth_hz <= 6000000)
+               ch_bw = 6000000;
+       else if (c->bandwidth_hz <= 7000000)
+               ch_bw = 7000000;
+       else
+               ch_bw = 8000000;
+
+       switch (c->delivery_system) {
+       case SYS_DVBT:
+               rcvr_mode = MT2063_OFFAIR_COFDM;
+               pict_car = 36125000;
+               pict2chanb_vsb = -(ch_bw / 2);
+               break;
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               rcvr_mode = MT2063_CABLE_QAM;
+               pict_car = 36125000;
+               pict2chanb_vsb = -(ch_bw / 2);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
+
+       state->AS_Data.f_LO2_Step = 125000;     /* FIXME: probably 5000 for FM */
+       state->AS_Data.f_out = if_mid;
+       state->AS_Data.f_out_bw = ch_bw + 750000;
+       status = MT2063_SetReceiverMode(state, rcvr_mode);
+       if (status < 0)
+               return status;
+
+       dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
+               c->frequency, ch_bw, pict2chanb_vsb);
+
+       status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
+
+       if (status < 0)
+               return status;
+
+       state->frequency = c->frequency;
+       return 0;
+}
+
+static int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+
+       dprintk(2, "\n");
+
+       if (!state->init)
+               return -ENODEV;
+
+       *freq = state->AS_Data.f_out;
+
+       dprintk(1, "IF frequency: %d\n", *freq);
+
+       return 0;
+}
+
+static int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+
+       dprintk(2, "\n");
+
+       if (!state->init)
+               return -ENODEV;
+
+       *bw = state->AS_Data.f_out_bw - 750000;
+
+       dprintk(1, "bandwidth: %d\n", *bw);
+
+       return 0;
+}
+
+static struct dvb_tuner_ops mt2063_ops = {
+       .info = {
+                .name = "MT2063 Silicon Tuner",
+                .frequency_min = 45000000,
+                .frequency_max = 850000000,
+                .frequency_step = 0,
+                },
+
+       .init = mt2063_init,
+       .sleep = MT2063_Sleep,
+       .get_status = mt2063_get_status,
+       .set_analog_params = mt2063_set_analog_params,
+       .set_params    = mt2063_set_params,
+       .get_if_frequency = mt2063_get_if_frequency,
+       .get_bandwidth = mt2063_get_bandwidth,
+       .release = mt2063_release,
+};
+
+struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+                                  struct mt2063_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       struct mt2063_state *state = NULL;
+
+       dprintk(2, "\n");
+
+       state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       state->config = config;
+       state->i2c = i2c;
+       state->frontend = fe;
+       state->reference = config->refclock / 1000;     /* kHz */
+       fe->tuner_priv = state;
+       fe->ops.tuner_ops = mt2063_ops;
+
+       printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
+       return fe;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(mt2063_attach);
+
+/*
+ * Ancillary routines visible outside mt2063
+ * FIXME: Remove them in favor of using standard tuner callbacks
+ */
+unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+       int err = 0;
+
+       dprintk(2, "\n");
+
+       err = MT2063_SoftwareShutdown(state, 1);
+       if (err < 0)
+               printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
+
+unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
+{
+       struct mt2063_state *state = fe->tuner_priv;
+       int err = 0;
+
+       dprintk(2, "\n");
+
+       err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
+       if (err < 0)
+               printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
+
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_DESCRIPTION("MT2063 Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mt2063.h b/drivers/media/common/tuners/mt2063.h
new file mode 100644 (file)
index 0000000..62d0e8e
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __MT2063_H__
+#define __MT2063_H__
+
+#include "dvb_frontend.h"
+
+struct mt2063_config {
+       u8 tuner_address;
+       u32 refclock;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_MT2063) || (defined(CONFIG_MEDIA_TUNER_MT2063_MODULE) && defined(MODULE))
+struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+                                  struct mt2063_config *config,
+                                  struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+                                  struct mt2063_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
+                                  u32 bw_in,
+                                  enum MTTune_atv_standard tv_type);
+
+/* FIXME: Should use the standard DVB attachment interfaces */
+unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
+unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
+
+#endif /* CONFIG_DVB_MT2063 */
+
+#endif /* __MT2063_H__ */
index a4f830bb25d1346a8961f15fd477d64023424604..f83b0c1ea6c86ad08e1f2252cde018077189d0db 100644 (file)
@@ -92,9 +92,9 @@ static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
        return 0;
 }
 
-static int mt2131_set_params(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *params)
+static int mt2131_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct mt2131_priv *priv;
        int ret=0, i;
        u32 freq;
@@ -105,12 +105,8 @@ static int mt2131_set_params(struct dvb_frontend *fe,
        u8 lockval = 0;
 
        priv = fe->tuner_priv;
-       if (fe->ops.info.type == FE_OFDM)
-               priv->bandwidth = params->u.ofdm.bandwidth;
-       else
-               priv->bandwidth = 0;
 
-       freq = params->frequency / 1000;  // Hz -> kHz
+       freq = c->frequency / 1000;  /* Hz -> kHz */
        dprintk(1, "%s() freq=%d\n", __func__, freq);
 
        f_lo1 = freq + MT2131_IF1 * 1000;
@@ -193,14 +189,6 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
-static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-       struct mt2131_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __func__);
-       *bandwidth = priv->bandwidth;
-       return 0;
-}
-
 static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
@@ -263,7 +251,6 @@ static const struct dvb_tuner_ops mt2131_tuner_ops = {
 
        .set_params    = mt2131_set_params,
        .get_frequency = mt2131_get_frequency,
-       .get_bandwidth = mt2131_get_bandwidth,
        .get_status    = mt2131_get_status
 };
 
@@ -281,7 +268,6 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
                return NULL;
 
        priv->cfg = cfg;
-       priv->bandwidth = 6000000; /* 6MHz */
        priv->i2c = i2c;
 
        if (mt2131_readreg(priv, 0, &id) != 0) {
index 4e05a67e88c1419580fe410450c07bf00c66f8e4..62aeedf5c5503198a606bbff9fe443c780ac288d 100644 (file)
@@ -38,7 +38,6 @@ struct mt2131_priv {
        struct i2c_adapter   *i2c;
 
        u32 frequency;
-       u32 bandwidth;
 };
 
 #endif /* __MT2131_PRIV_H__ */
index 25a8ea342c466d60a767d7d4b4ea622003125add..bca4d75e42d468a6e6662a222b792b38385601e5 100644 (file)
@@ -122,8 +122,9 @@ static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
 
 #define FREF 30000       // Quartz oscillator 30 MHz
 
-static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int mt2266_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct mt2266_priv *priv;
        int ret=0;
        u32 freq;
@@ -135,32 +136,32 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
 
        priv = fe->tuner_priv;
 
-       freq = params->frequency / 1000; // Hz -> kHz
+       freq = priv->frequency / 1000; /* Hz -> kHz */
        if (freq < 470000 && freq > 230000)
                return -EINVAL; /* Gap between VHF and UHF bands */
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
-       priv->frequency = freq * 1000;
 
+       priv->frequency = c->frequency;
        tune = 2 * freq * (8192/16) / (FREF/16);
        band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
        if (band == MT2266_VHF)
                tune *= 2;
 
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                mt2266_writeregs(priv, mt2266_init_6mhz,
                                 sizeof(mt2266_init_6mhz));
                break;
-       case BANDWIDTH_7_MHZ:
-               mt2266_writeregs(priv, mt2266_init_7mhz,
-                                sizeof(mt2266_init_7mhz));
-               break;
-       case BANDWIDTH_8_MHZ:
-       default:
+       case 8000000:
                mt2266_writeregs(priv, mt2266_init_8mhz,
                                 sizeof(mt2266_init_8mhz));
                break;
+       case 7000000:
+       default:
+               mt2266_writeregs(priv, mt2266_init_7mhz,
+                                sizeof(mt2266_init_7mhz));
+               break;
        }
+       priv->bandwidth = c->bandwidth_hz;
 
        if (band == MT2266_VHF && priv->band == MT2266_UHF) {
                dprintk("Switch from UHF to VHF");
index 54be9e6faaaf394c8be9020a39119af149058d28..6133315fb0e34ed5b48ba5e26c2bc48e249d8722 100644 (file)
@@ -3979,54 +3979,47 @@ static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
        return 0;
 }
 
-static int mxl5005s_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int mxl5005s_set_params(struct dvb_frontend *fe)
 {
        struct mxl5005s_state *state = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
        u32 req_mode, req_bw = 0;
        int ret;
 
        dprintk(1, "%s()\n", __func__);
 
-       if (fe->ops.info.type == FE_ATSC) {
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-                       req_mode = MXL_ATSC; break;
-               default:
-               case QAM_64:
-               case QAM_256:
-               case QAM_AUTO:
-                       req_mode = MXL_QAM; break;
-               }
-       } else
+       switch (delsys) {
+       case SYS_ATSC:
+               req_mode = MXL_ATSC;
+               req_bw  = MXL5005S_BANDWIDTH_6MHZ;
+               break;
+       case SYS_DVBC_ANNEX_B:
+               req_mode = MXL_QAM;
+               req_bw  = MXL5005S_BANDWIDTH_6MHZ;
+               break;
+       default:        /* Assume DVB-T */
                req_mode = MXL_DVBT;
-
-       /* Change tuner for new modulation type if reqd */
-       if (req_mode != state->current_mode) {
-               switch (req_mode) {
-               case MXL_ATSC:
-               case MXL_QAM:
-                       req_bw  = MXL5005S_BANDWIDTH_6MHZ;
+               switch (bw) {
+               case 6000000:
+                       req_bw = MXL5005S_BANDWIDTH_6MHZ;
+                       break;
+               case 7000000:
+                       req_bw = MXL5005S_BANDWIDTH_7MHZ;
+                       break;
+               case 8000000:
+               case 0:
+                       req_bw = MXL5005S_BANDWIDTH_8MHZ;
                        break;
-               case MXL_DVBT:
                default:
-                       /* Assume DVB-T */
-                       switch (params->u.ofdm.bandwidth) {
-                       case BANDWIDTH_6_MHZ:
-                               req_bw  = MXL5005S_BANDWIDTH_6MHZ;
-                               break;
-                       case BANDWIDTH_7_MHZ:
-                               req_bw  = MXL5005S_BANDWIDTH_7MHZ;
-                               break;
-                       case BANDWIDTH_AUTO:
-                       case BANDWIDTH_8_MHZ:
-                               req_bw  = MXL5005S_BANDWIDTH_8MHZ;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
+                       return -EINVAL;
                }
+       }
 
+       /* Change tuner for new modulation type if reqd */
+       if (req_mode != state->current_mode ||
+           req_bw != state->Chan_Bandwidth) {
                state->current_mode = req_mode;
                ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
 
@@ -4034,8 +4027,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
                ret = 0;
 
        if (ret == 0) {
-               dprintk(1, "%s() freq=%d\n", __func__, params->frequency);
-               ret = mxl5005s_SetRfFreqHz(fe, params->frequency);
+               dprintk(1, "%s() freq=%d\n", __func__, c->frequency);
+               ret = mxl5005s_SetRfFreqHz(fe, c->frequency);
        }
 
        return ret;
index 5d02221e99dd973ad674e56567bab4b369fae7ac..69e453ef0a1a8631ae3067fb9eb2780fa7768040 100644 (file)
@@ -165,6 +165,8 @@ struct mxl5007t_state {
        struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
        struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
 
+       enum mxl5007t_if_freq if_freq;
+
        u32 frequency;
        u32 bandwidth;
 };
@@ -286,6 +288,8 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
        /* set inverted IF or normal IF */
        set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
 
+       state->if_freq = if_freq;
+
        return;
 }
 
@@ -612,47 +616,43 @@ fail:
 
 /* ------------------------------------------------------------------------- */
 
-static int mxl5007t_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int mxl5007t_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
        struct mxl5007t_state *state = fe->tuner_priv;
        enum mxl5007t_bw_mhz bw;
        enum mxl5007t_mode mode;
        int ret;
-       u32 freq = params->frequency;
+       u32 freq = c->frequency;
 
-       if (fe->ops.info.type == FE_ATSC) {
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-               case VSB_16:
-                       mode = MxL_MODE_ATSC;
-                       break;
-               case QAM_64:
-               case QAM_256:
-                       mode = MxL_MODE_CABLE;
-                       break;
-               default:
-                       mxl_err("modulation not set!");
-                       return -EINVAL;
-               }
+       switch (delsys) {
+       case SYS_ATSC:
+               mode = MxL_MODE_ATSC;
+               bw = MxL_BW_6MHz;
+               break;
+       case SYS_DVBC_ANNEX_B:
+               mode = MxL_MODE_CABLE;
                bw = MxL_BW_6MHz;
-       } else if (fe->ops.info.type == FE_OFDM) {
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
+               break;
+       case SYS_DVBT:
+       case SYS_DVBT2:
+               mode = MxL_MODE_DVBT;
+               switch (c->bandwidth_hz) {
+               case 6000000:
                        bw = MxL_BW_6MHz;
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        bw = MxL_BW_7MHz;
                        break;
-               case BANDWIDTH_8_MHZ:
+               case 8000000:
                        bw = MxL_BW_8MHz;
                        break;
                default:
-                       mxl_err("bandwidth not set!");
                        return -EINVAL;
                }
-               mode = MxL_MODE_DVBT;
-       } else {
+               break;
+       default:
                mxl_err("modulation type not supported!");
                return -EINVAL;
        }
@@ -671,8 +671,7 @@ static int mxl5007t_set_params(struct dvb_frontend *fe,
                goto fail;
 
        state->frequency = freq;
-       state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
-               params->u.ofdm.bandwidth : 0;
+       state->bandwidth = c->bandwidth_hz;
 fail:
        mutex_unlock(&state->lock);
 
@@ -738,6 +737,50 @@ static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
        return 0;
 }
 
+static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+
+       *frequency = 0;
+
+       switch (state->if_freq) {
+       case MxL_IF_4_MHZ:
+               *frequency = 4000000;
+               break;
+       case MxL_IF_4_5_MHZ:
+               *frequency = 4500000;
+               break;
+       case MxL_IF_4_57_MHZ:
+               *frequency = 4570000;
+               break;
+       case MxL_IF_5_MHZ:
+               *frequency = 5000000;
+               break;
+       case MxL_IF_5_38_MHZ:
+               *frequency = 5380000;
+               break;
+       case MxL_IF_6_MHZ:
+               *frequency = 6000000;
+               break;
+       case MxL_IF_6_28_MHZ:
+               *frequency = 6280000;
+               break;
+       case MxL_IF_9_1915_MHZ:
+               *frequency = 9191500;
+               break;
+       case MxL_IF_35_25_MHZ:
+               *frequency = 35250000;
+               break;
+       case MxL_IF_36_15_MHZ:
+               *frequency = 36150000;
+               break;
+       case MxL_IF_44_MHZ:
+               *frequency = 44000000;
+               break;
+       }
+       return 0;
+}
+
 static int mxl5007t_release(struct dvb_frontend *fe)
 {
        struct mxl5007t_state *state = fe->tuner_priv;
@@ -767,6 +810,7 @@ static struct dvb_tuner_ops mxl5007t_tuner_ops = {
        .get_frequency     = mxl5007t_get_frequency,
        .get_bandwidth     = mxl5007t_get_bandwidth,
        .release           = mxl5007t_release,
+       .get_if_frequency  = mxl5007t_get_if_frequency,
 };
 
 static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
index 9f5dba244cb86e7e361e992bbd45fedd41b1a1f9..2d79b1f5d5ebcebe9a00321ee278239ca64d0a7f 100644 (file)
@@ -82,9 +82,9 @@ static void qt1010_dump_regs(struct qt1010_priv *priv)
        printk(KERN_CONT "\n");
 }
 
-static int qt1010_set_params(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *params)
+static int qt1010_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct qt1010_priv *priv;
        int err;
        u32 freq, div, mod1, mod2;
@@ -144,13 +144,11 @@ static int qt1010_set_params(struct dvb_frontend *fe,
 #define FREQ2  4000000 /* 4 MHz Quartz oscillator in the stick? */
 
        priv = fe->tuner_priv;
-       freq = params->frequency;
+       freq = c->frequency;
        div = (freq + QT1010_OFFSET) / QT1010_STEP;
        freq = (div * QT1010_STEP) - QT1010_OFFSET;
        mod1 = (freq + QT1010_OFFSET) % FREQ1;
        mod2 = (freq + QT1010_OFFSET) % FREQ2;
-       priv->bandwidth =
-               (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
        priv->frequency = freq;
 
        if (fe->ops.i2c_gate_ctrl)
@@ -320,7 +318,7 @@ static u8 qt1010_init_meas2(struct qt1010_priv *priv,
 static int qt1010_init(struct dvb_frontend *fe)
 {
        struct qt1010_priv *priv = fe->tuner_priv;
-       struct dvb_frontend_parameters params;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int err = 0;
        u8 i, tmpval, *valptr = NULL;
 
@@ -397,9 +395,9 @@ static int qt1010_init(struct dvb_frontend *fe)
                if ((err = qt1010_init_meas2(priv, i, &tmpval)))
                        return err;
 
-       params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+       c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
                                      /* MSI Megasky 580 GL861 533000000 */
-       return qt1010_set_params(fe, &params);
+       return qt1010_set_params(fe);
 }
 
 static int qt1010_release(struct dvb_frontend *fe)
@@ -416,10 +414,9 @@ static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
-static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-       struct qt1010_priv *priv = fe->tuner_priv;
-       *bandwidth = priv->bandwidth;
+       *frequency = 36125000;
        return 0;
 }
 
@@ -437,7 +434,7 @@ static const struct dvb_tuner_ops qt1010_tuner_ops = {
 
        .set_params    = qt1010_set_params,
        .get_frequency = qt1010_get_frequency,
-       .get_bandwidth = qt1010_get_bandwidth
+       .get_if_frequency = qt1010_get_if_frequency,
 };
 
 struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
index 090cf475f099ea567f5ea7899f684952b62f7795..2c42d3f016366d5f7cb8b11baebee9d1342a3ea3 100644 (file)
@@ -99,7 +99,6 @@ struct qt1010_priv {
        u8 reg25_init_val;
 
        u32 frequency;
-       u32 bandwidth;
 };
 
 #endif
index e29cc2bc113a91604f03b009a7f2877dd4a7d0e2..602c2e392b178c255a2d6fa476b8b2fa439f45d0 100644 (file)
@@ -25,6 +25,8 @@
 struct tda18212_priv {
        struct tda18212_config *cfg;
        struct i2c_adapter *i2c;
+
+       u32 if_frequency;
 };
 
 #define dbg(fmt, arg...)                                       \
@@ -128,20 +130,31 @@ static void tda18212_dump_regs(struct tda18212_priv *priv)
 }
 #endif
 
-static int tda18212_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int tda18212_set_params(struct dvb_frontend *fe)
 {
        struct tda18212_priv *priv = fe->tuner_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret, i;
        u32 if_khz;
        u8 buf[9];
+       #define DVBT_6   0
+       #define DVBT_7   1
+       #define DVBT_8   2
+       #define DVBT2_6  3
+       #define DVBT2_7  4
+       #define DVBT2_8  5
+       #define DVBC_6   6
+       #define DVBC_8   7
        static const u8 bw_params[][3] = {
-               /*  0f    13    23 */
-               { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
-               { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
-               { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
-               { 0x92, 0x53, 0x03 }, /* DVB-C */
+                    /* reg:   0f    13    23 */
+               [DVBT_6]  = { 0xb3, 0x20, 0x03 },
+               [DVBT_7]  = { 0xb3, 0x31, 0x01 },
+               [DVBT_8]  = { 0xb3, 0x22, 0x01 },
+               [DVBT2_6] = { 0xbc, 0x20, 0x03 },
+               [DVBT2_7] = { 0xbc, 0x72, 0x03 },
+               [DVBT2_8] = { 0xbc, 0x22, 0x01 },
+               [DVBC_6]  = { 0x92, 0x50, 0x03 },
+               [DVBC_8]  = { 0x92, 0x53, 0x03 },
        };
 
        dbg("delsys=%d RF=%d BW=%d\n",
@@ -155,24 +168,44 @@ static int tda18212_set_params(struct dvb_frontend *fe,
                switch (c->bandwidth_hz) {
                case 6000000:
                        if_khz = priv->cfg->if_dvbt_6;
-                       i = 0;
+                       i = DVBT_6;
                        break;
                case 7000000:
                        if_khz = priv->cfg->if_dvbt_7;
-                       i = 1;
+                       i = DVBT_7;
                        break;
                case 8000000:
                        if_khz = priv->cfg->if_dvbt_8;
-                       i = 2;
+                       i = DVBT_8;
                        break;
                default:
                        ret = -EINVAL;
                        goto error;
                }
                break;
-       case SYS_DVBC_ANNEX_AC:
+       case SYS_DVBT2:
+               switch (c->bandwidth_hz) {
+               case 6000000:
+                       if_khz = priv->cfg->if_dvbt2_6;
+                       i = DVBT2_6;
+                       break;
+               case 7000000:
+                       if_khz = priv->cfg->if_dvbt2_7;
+                       i = DVBT2_7;
+                       break;
+               case 8000000:
+                       if_khz = priv->cfg->if_dvbt2_8;
+                       i = DVBT2_8;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto error;
+               }
+               break;
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
                if_khz = priv->cfg->if_dvbc;
-               i = 3;
+               i = DVBC_8;
                break;
        default:
                ret = -EINVAL;
@@ -194,7 +227,7 @@ static int tda18212_set_params(struct dvb_frontend *fe,
        buf[0] = 0x02;
        buf[1] = bw_params[i][1];
        buf[2] = 0x03; /* default value */
-       buf[3] = if_khz / 50;
+       buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
        buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
        buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
        buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
@@ -204,6 +237,9 @@ static int tda18212_set_params(struct dvb_frontend *fe,
        if (ret)
                goto error;
 
+       /* actual IF rounded as it is on register */
+       priv->if_frequency = buf[3] * 50 * 1000;
+
 exit:
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
@@ -215,6 +251,15 @@ error:
        goto exit;
 }
 
+static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tda18212_priv *priv = fe->tuner_priv;
+
+       *frequency = priv->if_frequency;
+
+       return 0;
+}
+
 static int tda18212_release(struct dvb_frontend *fe)
 {
        kfree(fe->tuner_priv);
@@ -234,6 +279,7 @@ static const struct dvb_tuner_ops tda18212_tuner_ops = {
        .release       = tda18212_release,
 
        .set_params    = tda18212_set_params,
+       .get_if_frequency = tda18212_get_if_frequency,
 };
 
 struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
index 83b497f59e1b2e16b2a214bb4b6b06ec882778da..9bd5da4aabb7b032e13e6dc2ad7633d8d21b6971 100644 (file)
@@ -29,6 +29,10 @@ struct tda18212_config {
        u16 if_dvbt_6;
        u16 if_dvbt_7;
        u16 if_dvbt_8;
+       u16 if_dvbt2_5;
+       u16 if_dvbt2_6;
+       u16 if_dvbt2_7;
+       u16 if_dvbt2_8;
        u16 if_dvbc;
 };
 
index 4fc29730a12ccf2305739c34efa625deef0a1f95..dfb3a831df4540541757f5b6cc0ce7f23f989cd3 100644 (file)
@@ -109,10 +109,11 @@ static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
        return tda18218_rd_regs(priv, reg, val, 1);
 }
 
-static int tda18218_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int tda18218_set_params(struct dvb_frontend *fe)
 {
        struct tda18218_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 bw = c->bandwidth_hz;
        int ret;
        u8 buf[3], i, BP_Filter, LP_Fc;
        u32 LO_Frac;
@@ -138,22 +139,19 @@ static int tda18218_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
 
        /* low-pass filter cut-off frequency */
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       if (bw <= 6000000) {
                LP_Fc = 0;
-               LO_Frac = params->frequency + 3000000;
-               break;
-       case BANDWIDTH_7_MHZ:
+               priv->if_frequency = 3000000;
+       } else if (bw <= 7000000) {
                LP_Fc = 1;
-               LO_Frac = params->frequency + 3500000;
-               break;
-       case BANDWIDTH_8_MHZ:
-       default:
+               priv->if_frequency = 3500000;
+       } else {
                LP_Fc = 2;
-               LO_Frac = params->frequency + 4000000;
-               break;
+               priv->if_frequency = 4000000;
        }
 
+       LO_Frac = c->frequency + priv->if_frequency;
+
        /* band-pass filter */
        if (LO_Frac < 188000000)
                BP_Filter = 3;
@@ -206,6 +204,14 @@ error:
        return ret;
 }
 
+static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tda18218_priv *priv = fe->tuner_priv;
+       *frequency = priv->if_frequency;
+       dbg("%s: if=%d", __func__, *frequency);
+       return 0;
+}
+
 static int tda18218_sleep(struct dvb_frontend *fe)
 {
        struct tda18218_priv *priv = fe->tuner_priv;
@@ -268,6 +274,8 @@ static const struct dvb_tuner_ops tda18218_tuner_ops = {
        .sleep         = tda18218_sleep,
 
        .set_params    = tda18218_set_params,
+
+       .get_if_frequency = tda18218_get_if_frequency,
 };
 
 struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
index 904e5365c78c75402b73a9cbeaecff67810856fd..dc52b72e14071015255cb026354d44e4cf248fc6 100644 (file)
@@ -100,6 +100,8 @@ struct tda18218_priv {
        struct tda18218_config *cfg;
        struct i2c_adapter *i2c;
 
+       u32 if_frequency;
+
        u8 regs[TDA18218_NUM_REGS];
 };
 
index 63cc4004e211e9654044b612400460bb93832bf9..2e67f44599045e175ba6f0881bbb56bb6c11c578 100644 (file)
@@ -928,59 +928,49 @@ fail:
 
 /* ------------------------------------------------------------------ */
 
-static int tda18271_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int tda18271_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
+       u32 freq = c->frequency;
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_std_map *std_map = &priv->std;
        struct tda18271_std_map_item *map;
        int ret;
-       u32 bw, freq = params->frequency;
 
        priv->mode = TDA18271_DIGITAL;
 
-       if (fe->ops.info.type == FE_ATSC) {
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-               case VSB_16:
-                       map = &std_map->atsc_6;
-                       break;
-               case QAM_64:
-               case QAM_256:
-                       map = &std_map->qam_6;
-                       break;
-               default:
-                       tda_warn("modulation not set!\n");
-                       return -EINVAL;
-               }
-#if 0
-               /* userspace request is already center adjusted */
-               freq += 1750000; /* Adjust to center (+1.75MHZ) */
-#endif
+       switch (delsys) {
+       case SYS_ATSC:
+               map = &std_map->atsc_6;
                bw = 6000000;
-       } else if (fe->ops.info.type == FE_OFDM) {
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       bw = 6000000;
+               break;
+       case SYS_ISDBT:
+       case SYS_DVBT:
+       case SYS_DVBT2:
+               if (bw <= 6000000) {
                        map = &std_map->dvbt_6;
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       bw = 7000000;
+               } else if (bw <= 7000000) {
                        map = &std_map->dvbt_7;
-                       break;
-               case BANDWIDTH_8_MHZ:
-                       bw = 8000000;
+               } else {
                        map = &std_map->dvbt_8;
-                       break;
-               default:
-                       tda_warn("bandwidth not set!\n");
-                       return -EINVAL;
                }
-       } else if (fe->ops.info.type == FE_QAM) {
-               /* DVB-C */
-               map = &std_map->qam_8;
-               bw = 8000000;
-       } else {
+               break;
+       case SYS_DVBC_ANNEX_B:
+               bw = 6000000;
+               /* falltrough */
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               if (bw <= 6000000) {
+                       map = &std_map->qam_6;
+               } else if (bw <= 7000000) {
+                       map = &std_map->qam_7;
+               } else {
+                       map = &std_map->qam_8;
+               }
+               break;
+       default:
                tda_warn("modulation type not supported!\n");
                return -EINVAL;
        }
@@ -994,9 +984,9 @@ static int tda18271_set_params(struct dvb_frontend *fe,
        if (tda_fail(ret))
                goto fail;
 
+       priv->if_freq   = map->if_freq;
        priv->frequency = freq;
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
-               params->u.ofdm.bandwidth : 0;
+       priv->bandwidth = bw;
 fail:
        return ret;
 }
@@ -1050,6 +1040,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
        if (tda_fail(ret))
                goto fail;
 
+       priv->if_freq   = map->if_freq;
        priv->frequency = freq;
        priv->bandwidth = 0;
 fail:
@@ -1086,6 +1077,13 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
        return 0;
 }
 
+static int tda18271_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       *frequency = (u32)priv->if_freq * 1000;
+       return 0;
+}
+
 /* ------------------------------------------------------------------ */
 
 #define tda18271_update_std(std_cfg, name) do {                                \
@@ -1245,6 +1243,7 @@ static const struct dvb_tuner_ops tda18271_tuner_ops = {
        .set_config        = tda18271_set_config,
        .get_frequency     = tda18271_get_frequency,
        .get_bandwidth     = tda18271_get_bandwidth,
+       .get_if_frequency  = tda18271_get_if_frequency,
 };
 
 struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
index 3d5b6ab7e3322630814036cf65654f545cc7e095..fb881c667c9401aa355681816a5a7045d271183e 100644 (file)
@@ -1213,6 +1213,8 @@ static struct tda18271_std_map tda18271c1_std_map = {
                      .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_7    = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
        .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
                      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
@@ -1244,6 +1246,8 @@ static struct tda18271_std_map tda18271c2_std_map = {
                      .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_7    = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
        .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
                      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
index 94340f47562bbe36c01a5035a0633ff1c2149c72..454c152ccaa023d66423591108ca16616c058660 100644 (file)
@@ -122,6 +122,8 @@ struct tda18271_priv {
 
        struct mutex lock;
 
+       u16 if_freq;
+
        u32 frequency;
        u32 bandwidth;
 };
index 50cfa8cebb9309043e63059c350d7091e877e24c..640bae4e6a5a85c6db5274e9654b1d02f61c419b 100644 (file)
@@ -53,6 +53,7 @@ struct tda18271_std_map {
        struct tda18271_std_map_item dvbt_7;
        struct tda18271_std_map_item dvbt_8;
        struct tda18271_std_map_item qam_6;
+       struct tda18271_std_map_item qam_7;
        struct tda18271_std_map_item qam_8;
 };
 
index e0d5b43772b81e997ab6cd15199ae137c7bcb599..a0d17626747096b081d81add3ed5e072d964fd60 100644 (file)
@@ -152,9 +152,9 @@ static int tuner_transfer(struct dvb_frontend *fe,
        return rc;
 }
 
-static int tda827xo_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int tda827xo_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct tda827x_priv *priv = fe->tuner_priv;
        u8 buf[14];
        int rc;
@@ -165,18 +165,16 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
        u32 N;
 
        dprintk("%s:\n", __func__);
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       if (c->bandwidth_hz == 0) {
+               if_freq = 5000000;
+       } else if (c->bandwidth_hz <= 6000000) {
                if_freq = 4000000;
-               break;
-       case BANDWIDTH_7_MHZ:
+       } else if (c->bandwidth_hz <= 7000000) {
                if_freq = 4500000;
-               break;
-       default:                   /* 8 MHz or Auto */
+       } else {        /* 8 MHz */
                if_freq = 5000000;
-               break;
        }
-       tuner_freq = params->frequency;
+       tuner_freq = c->frequency;
 
        i = 0;
        while (tda827x_table[i].lomax < tuner_freq) {
@@ -220,8 +218,8 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
        if (rc < 0)
                goto err;
 
-       priv->frequency = params->frequency;
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+       priv->frequency = c->frequency;
+       priv->bandwidth = c->bandwidth_hz;
 
        return 0;
 
@@ -513,9 +511,9 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
        }
 }
 
-static int tda827xa_set_params(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *params)
+static int tda827xa_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct tda827x_priv *priv = fe->tuner_priv;
        struct tda827xa_data *frequency_map = tda827xa_dvbt;
        u8 buf[11];
@@ -531,22 +529,25 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        tda827xa_lna_gain(fe, 1, NULL);
        msleep(20);
 
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       if (c->bandwidth_hz == 0) {
+               if_freq = 5000000;
+       } else if (c->bandwidth_hz <= 6000000) {
                if_freq = 4000000;
-               break;
-       case BANDWIDTH_7_MHZ:
+       } else if (c->bandwidth_hz <= 7000000) {
                if_freq = 4500000;
-               break;
-       default:                   /* 8 MHz or Auto */
+       } else {        /* 8 MHz */
                if_freq = 5000000;
-               break;
        }
-       tuner_freq = params->frequency;
+       tuner_freq = c->frequency;
 
-       if (fe->ops.info.type == FE_QAM) {
+       switch (c->delivery_system) {
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
                dprintk("%s select tda827xa_dvbc\n", __func__);
                frequency_map = tda827xa_dvbc;
+               break;
+       default:
+               break;
        }
 
        i = 0;
@@ -645,9 +646,8 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        if (rc < 0)
                goto err;
 
-       priv->frequency = params->frequency;
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
-
+       priv->frequency = c->frequency;
+       priv->bandwidth = c->bandwidth_hz;
 
        return 0;
 
index f8ee29e6059c982e8e8ddce5cd0cbe28d78b58ed..39e7e583c8c0efb89335e6ab0c863ce77bd36db8 100644 (file)
@@ -751,6 +751,17 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
        if (4 != rc)
                tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
 
+       /* Write AUX byte */
+       switch (priv->type) {
+       case TUNER_PHILIPS_FM1216ME_MK3:
+               buffer[2] = 0x98;
+               buffer[3] = 0x20; /* set TOP AGC */
+               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;
 }
 
@@ -780,24 +791,26 @@ static int simple_set_params(struct dvb_frontend *fe,
 }
 
 static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
-                          const struct dvb_frontend_parameters *params)
+                          const u32 delsys,
+                          const u32 frequency,
+                          const u32 bandwidth)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
 
        switch (priv->type) {
        case TUNER_PHILIPS_FMD1216ME_MK3:
        case TUNER_PHILIPS_FMD1216MEX_MK3:
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
-                   params->frequency >= 158870000)
+               if (bandwidth == 8000000 &&
+                   frequency >= 158870000)
                        buf[3] |= 0x08;
                break;
        case TUNER_PHILIPS_TD1316:
                /* determine band */
-               buf[3] |= (params->frequency < 161000000) ? 1 :
-                         (params->frequency < 444000000) ? 2 : 4;
+               buf[3] |= (frequency < 161000000) ? 1 :
+                         (frequency < 444000000) ? 2 : 4;
 
                /* setup PLL filter */
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+               if (bandwidth == 8000000)
                        buf[3] |= 1 << 3;
                break;
        case TUNER_PHILIPS_TUV1236D:
@@ -808,12 +821,11 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
                if (dtv_input[priv->nr])
                        new_rf = dtv_input[priv->nr];
                else
-                       switch (params->u.vsb.modulation) {
-                       case QAM_64:
-                       case QAM_256:
+                       switch (delsys) {
+                       case SYS_DVBC_ANNEX_B:
                                new_rf = 1;
                                break;
-                       case VSB_8:
+                       case SYS_ATSC:
                        default:
                                new_rf = 0;
                                break;
@@ -827,7 +839,9 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
 }
 
 static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
-                               const struct dvb_frontend_parameters *params)
+                               const u32 delsys,
+                               const u32 freq,
+                               const u32 bw)
 {
        /* This function returns the tuned frequency on success, 0 on error */
        struct tuner_simple_priv *priv = fe->tuner_priv;
@@ -836,7 +850,7 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
        u8 config, cb;
        u32 div;
        int ret;
-       unsigned frequency = params->frequency / 62500;
+       u32 frequency = freq / 62500;
 
        if (!tun->stepsize) {
                /* tuner-core was loaded before the digital tuner was
@@ -860,7 +874,7 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
        buf[2] = config;
        buf[3] = cb;
 
-       simple_set_dvb(fe, buf, params);
+       simple_set_dvb(fe, buf, delsys, freq, bw);
 
        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]);
@@ -870,32 +884,37 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
 }
 
 static int simple_dvb_calc_regs(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *params,
                                u8 *buf, int buf_len)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
        struct tuner_simple_priv *priv = fe->tuner_priv;
        u32 frequency;
 
        if (buf_len < 5)
                return -EINVAL;
 
-       frequency = simple_dvb_configure(fe, buf+1, params);
+       frequency = simple_dvb_configure(fe, buf+1, delsys, c->frequency, bw);
        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;
+       priv->bandwidth = c->bandwidth_hz;
 
        return 5;
 }
 
-static int simple_dvb_set_params(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *params)
+static int simple_dvb_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
+       u32 freq = c->frequency;
        struct tuner_simple_priv *priv = fe->tuner_priv;
+       u32 frequency;
        u32 prev_freq, prev_bw;
        int ret;
        u8 buf[5];
@@ -906,9 +925,14 @@ static int simple_dvb_set_params(struct dvb_frontend *fe,
        prev_freq = priv->frequency;
        prev_bw   = priv->bandwidth;
 
-       ret = simple_dvb_calc_regs(fe, params, buf, 5);
-       if (ret != 5)
-               goto fail;
+       frequency = simple_dvb_configure(fe, buf+1, delsys, freq, bw);
+       if (frequency == 0)
+               return -EINVAL;
+
+       buf[0] = priv->i2c_props.addr;
+
+       priv->frequency = frequency;
+       priv->bandwidth = bw;
 
        /* put analog demod in standby when tuning digital */
        if (fe->ops.analog_ops.standby)
index 3acbaa04e1b3b3c6a4711211b5bf9acfe1e1dbe8..27555995f7e4c344f74afdfa14824ecbfac2b912 100644 (file)
@@ -311,7 +311,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
                   n_array, fname, name,
                   priv->firm_version >> 8, priv->firm_version & 0xff);
 
-       priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+       priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
        if (priv->firm == NULL) {
                tuner_err("Not enough memory to load firmware file.\n");
                rc = -ENOMEM;
@@ -891,7 +891,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
 
        /* Frequency is locked */
        if (frq_lock == 1)
-               signal = 32768;
+               signal = 1 << 11;
 
        /* Get SNR of the video signal */
        rc = xc2028_get_reg(priv, 0x0040, &signal);
@@ -962,14 +962,24 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
                 * For DTV 7/8, the firmware uses BW = 8000, so it needs a
                 * further adjustment to get the frequency center on VHF
                 */
+
+               /*
+                * The firmware DTV78 used to work fine in UHF band (8 MHz
+                * bandwidth) but not at all in VHF band (7 MHz bandwidth).
+                * The real problem was connected to the formula used to
+                * calculate the center frequency offset in VHF band.
+                * In fact, removing the 500KHz adjustment fixed the problem.
+                * This is coherent to what was implemented for the DTV7
+                * firmware.
+                * In the end, now the center frequency is the same for all 3
+                * firmwares (DTV7, DTV8, DTV78) and doesn't depend on channel
+                * bandwidth.
+                */
+
                if (priv->cur_fw.type & DTV6)
                        offset = 1750000;
-               else if (priv->cur_fw.type & DTV7)
-                       offset = 2250000;
-               else    /* DTV8 or DTV78 */
+               else    /* DTV7 or DTV8 or DTV78 */
                        offset = 2750000;
-               if ((priv->cur_fw.type & DTV78) && freq < 470000000)
-                       offset -= 500000;
 
                /*
                 * xc3028 additional "magic"
@@ -979,17 +989,13 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
                 * newer firmwares
                 */
 
-#if 1
                /*
                 * The proper adjustment would be to do it at s-code table.
                 * However, this didn't work, as reported by
                 * Robert Lowery <rglowery@exemail.com.au>
                 */
 
-               if (priv->cur_fw.type & DTV7)
-                       offset += 500000;
-
-#else
+#if 0
                /*
                 * Still need tests for XC3028L (firmware 3.2 or upper)
                 * So, for now, let's just comment the per-firmware
@@ -1084,68 +1090,28 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
                                V4L2_TUNER_ANALOG_TV, type, p->std, 0);
 }
 
-static int xc2028_set_params(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *p)
+static int xc2028_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
        struct xc2028_data *priv = fe->tuner_priv;
        unsigned int       type=0;
-       fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
        u16                demod = 0;
 
        tuner_dbg("%s called\n", __func__);
 
-       switch(fe->ops.info.type) {
-       case FE_OFDM:
-               bw = p->u.ofdm.bandwidth;
+       switch (delsys) {
+       case SYS_DVBT:
+       case SYS_DVBT2:
                /*
                 * The only countries with 6MHz seem to be Taiwan/Uruguay.
                 * Both seem to require QAM firmware for OFDM decoding
                 * Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
                 */
-               if (bw == BANDWIDTH_6_MHZ)
+               if (bw <= 6000000)
                        type |= QAM;
-               break;
-       case FE_ATSC:
-               bw = BANDWIDTH_6_MHZ;
-               /* The only ATSC firmware (at least on v2.7) is D2633 */
-               type |= ATSC | D2633;
-               break;
-       /* DVB-S and pure QAM (FE_QAM) are not supported */
-       default:
-               return -EINVAL;
-       }
-
-       switch (bw) {
-       case BANDWIDTH_8_MHZ:
-               if (p->frequency < 470000000)
-                       priv->ctrl.vhfbw7 = 0;
-               else
-                       priv->ctrl.uhfbw8 = 1;
-               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
-               type |= F8MHZ;
-               break;
-       case BANDWIDTH_7_MHZ:
-               if (p->frequency < 470000000)
-                       priv->ctrl.vhfbw7 = 1;
-               else
-                       priv->ctrl.uhfbw8 = 0;
-               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
-               type |= F8MHZ;
-               break;
-       case BANDWIDTH_6_MHZ:
-               type |= DTV6;
-               priv->ctrl.vhfbw7 = 0;
-               priv->ctrl.uhfbw8 = 0;
-               break;
-       default:
-               tuner_err("error: bandwidth not supported.\n");
-       };
 
-       /*
-         Selects between D2633 or D2620 firmware.
-         It doesn't make sense for ATSC, since it should be D2633 on all cases
-        */
-       if (fe->ops.info.type != FE_ATSC) {
                switch (priv->ctrl.type) {
                case XC2028_D2633:
                        type |= D2633;
@@ -1161,6 +1127,34 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                        else
                                type |= D2620;
                }
+               break;
+       case SYS_ATSC:
+               /* The only ATSC firmware (at least on v2.7) is D2633 */
+               type |= ATSC | D2633;
+               break;
+       /* DVB-S and pure QAM (FE_QAM) are not supported */
+       default:
+               return -EINVAL;
+       }
+
+       if (bw <= 6000000) {
+               type |= DTV6;
+               priv->ctrl.vhfbw7 = 0;
+               priv->ctrl.uhfbw8 = 0;
+       } else if (bw <= 7000000) {
+               if (c->frequency < 470000000)
+                       priv->ctrl.vhfbw7 = 1;
+               else
+                       priv->ctrl.uhfbw8 = 0;
+               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
+               type |= F8MHZ;
+       } else {
+               if (c->frequency < 470000000)
+                       priv->ctrl.vhfbw7 = 0;
+               else
+                       priv->ctrl.uhfbw8 = 1;
+               type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
+               type |= F8MHZ;
        }
 
        /* All S-code tables need a 200kHz shift */
@@ -1185,7 +1179,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                 */
        }
 
-       return generic_set_freq(fe, p->frequency,
+       return generic_set_freq(fe, c->frequency,
                                V4L2_TUNER_DIGITAL_TV, type, 0, demod);
 }
 
index 634f4d9b6c6380678bf879e50293e9254a813e13..d218c1d68c33a622cdc791aa684e5645441965bf 100644 (file)
@@ -758,7 +758,7 @@ static int xc4000_fwupload(struct dvb_frontend *fe)
                n_array, fname, name,
                priv->firm_version >> 8, priv->firm_version & 0xff);
 
-       priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+       priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
        if (priv->firm == NULL) {
                printk(KERN_ERR "Not enough memory to load firmware file.\n");
                rc = -ENOMEM;
@@ -1121,83 +1121,62 @@ static void xc_debug_dump(struct xc4000_priv *priv)
        dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
 }
 
-static int xc4000_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int xc4000_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys = c->delivery_system;
+       u32 bw = c->bandwidth_hz;
        struct xc4000_priv *priv = fe->tuner_priv;
        unsigned int type;
        int     ret = -EREMOTEIO;
 
-       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, c->frequency);
 
        mutex_lock(&priv->lock);
 
-       if (fe->ops.info.type == FE_ATSC) {
-               dprintk(1, "%s() ATSC\n", __func__);
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-               case VSB_16:
-                       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;
-                       priv->video_standard = XC4000_DTV6;
-                       type = DTV6;
-                       break;
-               case QAM_64:
-               case QAM_256:
-               case QAM_AUTO:
-                       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;
-                       priv->video_standard = XC4000_DTV6;
-                       type = DTV6;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       goto fail;
-               }
-       } else if (fe->ops.info.type == FE_OFDM) {
+       switch (delsys) {
+       case SYS_ATSC:
+               dprintk(1, "%s() VSB modulation\n", __func__);
+               priv->rf_mode = XC_RF_MODE_AIR;
+               priv->freq_hz = c->frequency - 1750000;
+               priv->video_standard = XC4000_DTV6;
+               type = DTV6;
+               break;
+       case SYS_DVBC_ANNEX_B:
+               dprintk(1, "%s() QAM modulation\n", __func__);
+               priv->rf_mode = XC_RF_MODE_CABLE;
+               priv->freq_hz = c->frequency - 1750000;
+               priv->video_standard = XC4000_DTV6;
+               type = DTV6;
+               break;
+       case SYS_DVBT:
+       case SYS_DVBT2:
                dprintk(1, "%s() OFDM\n", __func__);
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       priv->bandwidth = BANDWIDTH_6_MHZ;
+               if (bw == 0) {
+                       if (c->frequency < 400000000) {
+                               priv->freq_hz = c->frequency - 2250000;
+                       } else {
+                               priv->freq_hz = c->frequency - 2750000;
+                       }
+                       priv->video_standard = XC4000_DTV7_8;
+                       type = DTV78;
+               } else if (bw <= 6000000) {
                        priv->video_standard = XC4000_DTV6;
-                       priv->freq_hz = params->frequency - 1750000;
+                       priv->freq_hz = c->frequency - 1750000;
                        type = DTV6;
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       priv->bandwidth = BANDWIDTH_7_MHZ;
+               } else if (bw <= 7000000) {
                        priv->video_standard = XC4000_DTV7;
-                       priv->freq_hz = params->frequency - 2250000;
+                       priv->freq_hz = c->frequency - 2250000;
                        type = DTV7;
-                       break;
-               case BANDWIDTH_8_MHZ:
-                       priv->bandwidth = BANDWIDTH_8_MHZ;
+               } else {
                        priv->video_standard = XC4000_DTV8;
-                       priv->freq_hz = params->frequency - 2750000;
+                       priv->freq_hz = c->frequency - 2750000;
                        type = DTV8;
-                       break;
-               case BANDWIDTH_AUTO:
-                       if (params->frequency < 400000000) {
-                               priv->bandwidth = BANDWIDTH_7_MHZ;
-                               priv->freq_hz = params->frequency - 2250000;
-                       } else {
-                               priv->bandwidth = BANDWIDTH_8_MHZ;
-                               priv->freq_hz = params->frequency - 2750000;
-                       }
-                       priv->video_standard = XC4000_DTV7_8;
-                       type = DTV78;
-                       break;
-               default:
-                       printk(KERN_ERR "xc4000 bandwidth not set!\n");
-                       ret = -EINVAL;
-                       goto fail;
                }
                priv->rf_mode = XC_RF_MODE_AIR;
-       } else {
-               printk(KERN_ERR "xc4000 modulation type not supported!\n");
+               break;
+       default:
+               printk(KERN_ERR "xc4000 delivery system not supported!\n");
                ret = -EINVAL;
                goto fail;
        }
@@ -1209,6 +1188,8 @@ static int xc4000_set_params(struct dvb_frontend *fe,
        if (check_firmware(fe, type, 0, priv->if_khz) != 0)
                goto fail;
 
+       priv->bandwidth = c->bandwidth_hz;
+
        ret = xc_set_signal_source(priv, priv->rf_mode);
        if (ret != 0) {
                printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
@@ -1605,7 +1586,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
                break;
        case 1:
                /* new tuner instance */
-               priv->bandwidth = BANDWIDTH_6_MHZ;
+               priv->bandwidth = 6000000;
                /* set default configuration */
                priv->if_khz = 4560;
                priv->default_pm = 0;
index aa1b2e844d3206b8c2bcc96ddaab3f583f7e2739..296df05b8cda8fbe66ab430d0988f647807e5ac0 100644 (file)
@@ -628,20 +628,13 @@ static void xc_debug_dump(struct xc5000_priv *priv)
        dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
 }
 
-/*
- * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
- *     Bw = Symbol_rate * (1 + 0.15)
- * As such, the maximum symbol rate supported by 6 MHz is given by:
- *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
- */
-#define MAX_SYMBOL_RATE_6MHz   5217391
-
-static int xc5000_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int xc5000_set_params(struct dvb_frontend *fe)
 {
+       int ret, b;
        struct xc5000_priv *priv = fe->tuner_priv;
-       int ret;
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       u32 freq = fe->dtv_property_cache.frequency;
+       u32 delsys  = fe->dtv_property_cache.delivery_system;
 
        if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
                if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
@@ -650,88 +643,69 @@ static int xc5000_set_params(struct dvb_frontend *fe,
                }
        }
 
-       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
-
-       if (fe->ops.info.type == FE_ATSC) {
-               dprintk(1, "%s() ATSC\n", __func__);
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-               case VSB_16:
-                       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;
-                       priv->video_standard = DTV6;
-                       break;
-               case QAM_64:
-               case QAM_256:
-               case QAM_AUTO:
-                       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;
-                       priv->video_standard = DTV6;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else if (fe->ops.info.type == FE_OFDM) {
+       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
+
+       switch (delsys) {
+       case SYS_ATSC:
+               dprintk(1, "%s() VSB modulation\n", __func__);
+               priv->rf_mode = XC_RF_MODE_AIR;
+               priv->freq_hz = freq - 1750000;
+               priv->video_standard = DTV6;
+               break;
+       case SYS_DVBC_ANNEX_B:
+               dprintk(1, "%s() QAM modulation\n", __func__);
+               priv->rf_mode = XC_RF_MODE_CABLE;
+               priv->freq_hz = freq - 1750000;
+               priv->video_standard = DTV6;
+               break;
+       case SYS_DVBT:
+       case SYS_DVBT2:
                dprintk(1, "%s() OFDM\n", __func__);
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       priv->bandwidth = BANDWIDTH_6_MHZ;
+               switch (bw) {
+               case 6000000:
                        priv->video_standard = DTV6;
-                       priv->freq_hz = params->frequency - 1750000;
+                       priv->freq_hz = freq - 1750000;
                        break;
-               case BANDWIDTH_7_MHZ:
-                       printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n");
-                       return -EINVAL;
-               case BANDWIDTH_8_MHZ:
-                       priv->bandwidth = BANDWIDTH_8_MHZ;
+               case 7000000:
+                       priv->video_standard = DTV7;
+                       priv->freq_hz = freq - 2250000;
+                       break;
+               case 8000000:
                        priv->video_standard = DTV8;
-                       priv->freq_hz = params->frequency - 2750000;
+                       priv->freq_hz = freq - 2750000;
                        break;
                default:
                        printk(KERN_ERR "xc5000 bandwidth not set!\n");
                        return -EINVAL;
                }
                priv->rf_mode = XC_RF_MODE_AIR;
-       } else if (fe->ops.info.type == FE_QAM) {
-               switch (params->u.qam.modulation) {
-               case QAM_256:
-               case QAM_AUTO:
-               case QAM_16:
-               case QAM_32:
-               case QAM_64:
-               case QAM_128:
-                       dprintk(1, "%s() QAM modulation\n", __func__);
-                       priv->rf_mode = XC_RF_MODE_CABLE;
-                       /*
-                        * Using a 8MHz bandwidth sometimes fail
-                        * with 6MHz-spaced channels, due to inter-carrier
-                        * interference. So, use DTV6 firmware
-                        */
-                       if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) {
-                               priv->bandwidth = BANDWIDTH_6_MHZ;
-                               priv->video_standard = DTV6;
-                               priv->freq_hz = params->frequency - 1750000;
-                       } else {
-                               priv->bandwidth = BANDWIDTH_8_MHZ;
-                               priv->video_standard = DTV7_8;
-                               priv->freq_hz = params->frequency - 2750000;
-                       }
-                       break;
-               default:
-                       dprintk(1, "%s() Unsupported QAM type\n", __func__);
-                       return -EINVAL;
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               dprintk(1, "%s() QAM modulation\n", __func__);
+               priv->rf_mode = XC_RF_MODE_CABLE;
+               if (bw <= 6000000) {
+                       priv->video_standard = DTV6;
+                       priv->freq_hz = freq - 1750000;
+                       b = 6;
+               } else if (bw <= 7000000) {
+                       priv->video_standard = DTV7;
+                       priv->freq_hz = freq - 2250000;
+                       b = 7;
+               } else {
+                       priv->video_standard = DTV7_8;
+                       priv->freq_hz = freq - 2750000;
+                       b = 8;
                }
-       } else {
-               printk(KERN_ERR "xc5000 modulation type not supported!\n");
+               dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
+                       b, bw);
+               break;
+       default:
+               printk(KERN_ERR "xc5000: delivery system is not supported!\n");
                return -EINVAL;
        }
 
-       dprintk(1, "%s() frequency=%d (compensated)\n",
-               __func__, priv->freq_hz);
+       dprintk(1, "%s() frequency=%d (compensated to %d)\n",
+               __func__, freq, priv->freq_hz);
 
        ret = xc_SetSignalSource(priv, priv->rf_mode);
        if (ret != XC_RESULT_SUCCESS) {
@@ -763,6 +737,8 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        if (debug)
                xc_debug_dump(priv);
 
+       priv->bandwidth = bw;
+
        return 0;
 }
 
@@ -968,6 +944,14 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
        return 0;
 }
 
+static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+       struct xc5000_priv *priv = fe->tuner_priv;
+       dprintk(1, "%s()\n", __func__);
+       *freq = priv->if_khz * 1000;
+       return 0;
+}
+
 static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
@@ -1108,6 +1092,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
        .set_params        = xc5000_set_params,
        .set_analog_params = xc5000_set_analog_params,
        .get_frequency     = xc5000_get_frequency,
+       .get_if_frequency  = xc5000_get_if_frequency,
        .get_bandwidth     = xc5000_get_bandwidth,
        .get_status        = xc5000_get_status
 };
@@ -1135,7 +1120,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                break;
        case 1:
                /* new tuner instance */
-               priv->bandwidth = BANDWIDTH_6_MHZ;
+               priv->bandwidth = 6000000;
                fe->tuner_priv = priv;
                break;
        default:
index 2df1b0214dcdce8bbb139990c18b74c8f9cc5a7b..b1e8c99f469b403005cdb9ff7680050c1ea6278b 100644 (file)
@@ -86,7 +86,8 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
        fc->demux.stop_feed = flexcop_dvb_stop_feed;
        fc->demux.write_to_decoder = NULL;
 
-       if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
+       ret = dvb_dmx_init(&fc->demux);
+       if (ret < 0) {
                err("dvb_dmx failed: error %d", ret);
                goto err_dmx;
        }
@@ -96,32 +97,42 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
        fc->dmxdev.filternum = fc->demux.feednum;
        fc->dmxdev.demux = &fc->demux.dmx;
        fc->dmxdev.capabilities = 0;
-       if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
+       ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter);
+       if (ret < 0) {
                err("dvb_dmxdev_init failed: error %d", ret);
                goto err_dmx_dev;
        }
 
-       if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+       ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend);
+       if (ret < 0) {
                err("adding hw_frontend to dmx failed: error %d", ret);
                goto err_dmx_add_hw_frontend;
        }
 
        fc->mem_frontend.source = DMX_MEMORY_FE;
-       if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) {
+       ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend);
+       if (ret < 0) {
                err("adding mem_frontend to dmx failed: error %d", ret);
                goto err_dmx_add_mem_frontend;
        }
 
-       if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+       ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend);
+       if (ret < 0) {
                err("connect frontend failed: error %d", ret);
                goto err_connect_frontend;
        }
 
-       dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+       ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+       if (ret < 0) {
+               err("dvb_net_init failed: error %d", ret);
+               goto err_net;
+       }
 
        fc->init_state |= FC_STATE_DVB_INIT;
        return 0;
 
+err_net:
+       fc->demux.dmx.disconnect_frontend(&fc->demux.dmx);
 err_connect_frontend:
        fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend);
 err_dmx_add_mem_frontend:
@@ -254,7 +265,8 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        flexcop_hw_filter_init(fc);
        flexcop_smc_ctrl(fc, 0);
 
-       if ((ret = flexcop_dvb_init(fc)))
+       ret = flexcop_dvb_init(fc);
+       if (ret)
                goto error;
 
        /* i2c has to be done before doing EEProm stuff -
@@ -272,7 +284,8 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        } else
                warn("reading of MAC address failed.\n");
 
-       if ((ret = flexcop_frontend_init(fc)))
+       ret = flexcop_frontend_init(fc);
+       if (ret)
                goto error;
 
        flexcop_device_name(fc,"initialization of","complete");
index caa4e18ed1c188d4d20575f184f2bf67572358ff..430b3eb118152c1c3606e4cf355f3a925777f672 100644 (file)
@@ -386,7 +386,7 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
        return 0;
 }
 
-static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
+static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
 {
        state->bandwidth = bandwidth;
 
@@ -394,7 +394,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
                return -EOPNOTSUPP;
 
        switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
                        state->tx_tuna[7] = 0x06;
                else {
@@ -402,7 +402,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
                        state->tx_tuna[7] = 0x00;
                }
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
                        state->tx_tuna[7] = 0x07;
                else {
@@ -410,7 +410,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
                        state->tx_tuna[7] = 0x00;
                }
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
                        state->tx_tuna[7] = 0x08;
                else {
@@ -1561,7 +1561,7 @@ static int dst_init(struct dvb_frontend *fe)
        state->tone = SEC_TONE_OFF;
        state->diseq_flags = 0;
        state->k22 = 0x02;
-       state->bandwidth = BANDWIDTH_7_MHZ;
+       state->bandwidth = 7000000;
        state->cur_jiff = jiffies;
        if (state->dst_type == DST_TYPE_IS_SAT)
                memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
@@ -1609,8 +1609,9 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
        return retval;
 }
 
-static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        int retval = -EINVAL;
        struct dst_state *state = fe->demodulator_priv;
 
@@ -1623,17 +1624,17 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
                if (state->dst_type == DST_TYPE_IS_SAT) {
                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
                                dst_set_inversion(state, p->inversion);
-                       dst_set_fec(state, p->u.qpsk.fec_inner);
-                       dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+                       dst_set_fec(state, p->fec_inner);
+                       dst_set_symbolrate(state, p->symbol_rate);
                        dst_set_polarization(state);
-                       dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+                       dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
 
                } else if (state->dst_type == DST_TYPE_IS_TERR)
-                       dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+                       dst_set_bandwidth(state, p->bandwidth_hz);
                else if (state->dst_type == DST_TYPE_IS_CABLE) {
-                       dst_set_fec(state, p->u.qam.fec_inner);
-                       dst_set_symbolrate(state, p->u.qam.symbol_rate);
-                       dst_set_modulation(state, p->u.qam.modulation);
+                       dst_set_fec(state, p->fec_inner);
+                       dst_set_symbolrate(state, p->symbol_rate);
+                       dst_set_modulation(state, p->modulation);
                }
                retval = dst_write_tuna(fe);
        }
@@ -1642,31 +1643,32 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
 }
 
 static int dst_tune_frontend(struct dvb_frontend* fe,
-                           struct dvb_frontend_parameters* p,
+                           bool re_tune,
                            unsigned int mode_flags,
                            unsigned int *delay,
                            fe_status_t *status)
 {
        struct dst_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
-       if (p != NULL) {
+       if (re_tune) {
                dst_set_freq(state, p->frequency);
                dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
 
                if (state->dst_type == DST_TYPE_IS_SAT) {
                        if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
                                dst_set_inversion(state, p->inversion);
-                       dst_set_fec(state, p->u.qpsk.fec_inner);
-                       dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+                       dst_set_fec(state, p->fec_inner);
+                       dst_set_symbolrate(state, p->symbol_rate);
                        dst_set_polarization(state);
-                       dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+                       dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
 
                } else if (state->dst_type == DST_TYPE_IS_TERR)
-                       dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+                       dst_set_bandwidth(state, p->bandwidth_hz);
                else if (state->dst_type == DST_TYPE_IS_CABLE) {
-                       dst_set_fec(state, p->u.qam.fec_inner);
-                       dst_set_symbolrate(state, p->u.qam.symbol_rate);
-                       dst_set_modulation(state, p->u.qam.modulation);
+                       dst_set_fec(state, p->fec_inner);
+                       dst_set_symbolrate(state, p->symbol_rate);
+                       dst_set_modulation(state, p->modulation);
                }
                dst_write_tuna(fe);
        }
@@ -1683,22 +1685,23 @@ static int dst_get_tuning_algo(struct dvb_frontend *fe)
        return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
 }
 
-static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dst_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct dst_state *state = fe->demodulator_priv;
 
        p->frequency = state->decode_freq;
        if (state->dst_type == DST_TYPE_IS_SAT) {
                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
                        p->inversion = state->inversion;
-               p->u.qpsk.symbol_rate = state->symbol_rate;
-               p->u.qpsk.fec_inner = dst_get_fec(state);
+               p->symbol_rate = state->symbol_rate;
+               p->fec_inner = dst_get_fec(state);
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
-               p->u.ofdm.bandwidth = state->bandwidth;
+               p->bandwidth_hz = state->bandwidth;
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
-               p->u.qam.symbol_rate = state->symbol_rate;
-               p->u.qam.fec_inner = dst_get_fec(state);
-               p->u.qam.modulation = dst_get_modulation(state);
+               p->symbol_rate = state->symbol_rate;
+               p->fec_inner = dst_get_fec(state);
+               p->modulation = dst_get_modulation(state);
        }
 
        return 0;
@@ -1756,10 +1759,9 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
 EXPORT_SYMBOL(dst_attach);
 
 static struct dvb_frontend_ops dst_dvbt_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "DST DVB-T",
-               .type = FE_OFDM,
                .frequency_min = 137000000,
                .frequency_max = 858000000,
                .frequency_stepsize = 166667,
@@ -1786,10 +1788,9 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
 };
 
 static struct dvb_frontend_ops dst_dvbs_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name = "DST DVB-S",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1000,     /* kHz for QPSK frontends */
@@ -1816,10 +1817,9 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
 };
 
 static struct dvb_frontend_ops dst_dvbc_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A },
        .info = {
                .name = "DST DVB-C",
-               .type = FE_QAM,
                .frequency_stepsize = 62500,
                .frequency_min = 51000000,
                .frequency_max = 858000000,
@@ -1846,9 +1846,9 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
 };
 
 static struct dvb_frontend_ops dst_atsc_ops = {
+       .delsys = { SYS_ATSC },
        .info = {
                .name = "DST ATSC",
-               .type = FE_ATSC,
                .frequency_stepsize = 62500,
                .frequency_min = 510000000,
                .frequency_max = 858000000,
index d88cf2add82b6b20010b6b1c92c7f8d6d139b784..d70d98f1a5716775c2b9163a80fccfb56051ef6c 100644 (file)
@@ -124,7 +124,7 @@ struct dst_state {
        u16 decode_snr;
        unsigned long cur_jiff;
        u8 k22;
-       fe_bandwidth_t bandwidth;
+       u32 bandwidth;
        u32 dst_hw_cap;
        u8 dst_fw_version;
        fe_sec_mini_cmd_t minicmd;
index 521d691049824523f7229335bf0eb267f976376f..81fab9adc1cad18de7d3f24420893fdc894f1994 100644 (file)
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) "dvb_bt8xx: " fmt
+
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -148,8 +150,9 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend *fe, u8* pllbuf, int buf_len)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
@@ -157,18 +160,18 @@ static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_f
        if (buf_len < 5)
                return -EINVAL;
 
-       div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+       div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       if (params->frequency < 542000000)
+       if (c->frequency < 542000000)
                cp = 0xb4;
-       else if (params->frequency < 771000000)
+       else if (c->frequency < 771000000)
                cp = 0xbc;
        else
                cp = 0xf4;
 
-       if (params->frequency == 0)
+       if (c->frequency == 0)
                bs = 0x03;
-       else if (params->frequency < 443250000)
+       else if (c->frequency < 443250000)
                bs = 0x02;
        else
                bs = 0x08;
@@ -191,13 +194,12 @@ static struct zl10353_config thomson_dtt7579_zl10353_config = {
        .demod_address = 0x0f,
 };
 
-static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int cx24108_tuner_set_params(struct dvb_frontend *fe)
 {
-       u32 freq = params->frequency;
-
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 freq = c->frequency;
        int i, a, n, pump;
        u32 band, pll;
-
        u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
                1576000,1718000,1856000,2036000,2150000};
        u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
@@ -205,7 +207,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
                0x00120000,0x00140000};
 
        #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
-       printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
+       dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq);
 
        /* This is really the bit driving the tuner chip cx24108 */
 
@@ -216,7 +218,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
 
        /* decide which VCO to use for the input frequency */
        for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++);
-       printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
+       dprintk("cx24108 debug: select vco #%d (f=%d)\n", i, freq);
        band=bandsel[i];
        /* the gain values must be set by SetSymbolrate */
        /* compute the pll divider needed, from Conexant data sheet,
@@ -232,7 +234,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
            ((a&0x1f)<<11);
        /* everything is shifted left 11 bits to left-align the bits in the
           32bit word. Output to the tuner goes MSB-aligned, after all */
-       printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
+       dprintk("cx24108 debug: pump=%d, n=%d, a=%d\n", pump, n, a);
        cx24110_pll_write(fe,band);
        /* set vga and vca to their widest-band settings, as a precaution.
           SetSymbolrate might not be called to set this up */
@@ -267,31 +269,32 @@ static struct cx24110_config pctvsat_config = {
        .demod_address = 0x55,
 };
 
-static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 cfg, cpump, band_select;
        u8 data[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (36000000 + params->frequency + 83333) / 166666;
+       div = (36000000 + c->frequency + 83333) / 166666;
        cfg = 0x88;
 
-       if (params->frequency < 175000000)
+       if (c->frequency < 175000000)
                cpump = 2;
-       else if (params->frequency < 390000000)
+       else if (c->frequency < 390000000)
                cpump = 1;
-       else if (params->frequency < 470000000)
+       else if (c->frequency < 470000000)
                cpump = 2;
-       else if (params->frequency < 750000000)
+       else if (c->frequency < 750000000)
                cpump = 2;
        else
                cpump = 3;
 
-       if (params->frequency < 175000000)
+       if (c->frequency < 175000000)
                band_select = 0x0e;
-       else if (params->frequency < 470000000)
+       else if (c->frequency < 470000000)
                band_select = 0x05;
        else
                band_select = 0x03;
@@ -342,50 +345,51 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend *fe, u8 *pllbuf, int buf_len)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
 
        if (buf_len < 5) return -EINVAL;
 
-       div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+       div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       if (params->frequency < 150000000)
+       if (c->frequency < 150000000)
                cp = 0xB4;
-       else if (params->frequency < 173000000)
+       else if (c->frequency < 173000000)
                cp = 0xBC;
-       else if (params->frequency < 250000000)
+       else if (c->frequency < 250000000)
                cp = 0xB4;
-       else if (params->frequency < 400000000)
+       else if (c->frequency < 400000000)
                cp = 0xBC;
-       else if (params->frequency < 420000000)
+       else if (c->frequency < 420000000)
                cp = 0xF4;
-       else if (params->frequency < 470000000)
+       else if (c->frequency < 470000000)
                cp = 0xFC;
-       else if (params->frequency < 600000000)
+       else if (c->frequency < 600000000)
                cp = 0xBC;
-       else if (params->frequency < 730000000)
+       else if (c->frequency < 730000000)
                cp = 0xF4;
        else
                cp = 0xFC;
 
-       if (params->frequency < 150000000)
+       if (c->frequency < 150000000)
                bs = 0x01;
-       else if (params->frequency < 173000000)
+       else if (c->frequency < 173000000)
                bs = 0x01;
-       else if (params->frequency < 250000000)
+       else if (c->frequency < 250000000)
                bs = 0x02;
-       else if (params->frequency < 400000000)
+       else if (c->frequency < 400000000)
                bs = 0x02;
-       else if (params->frequency < 420000000)
+       else if (c->frequency < 420000000)
                bs = 0x02;
-       else if (params->frequency < 470000000)
+       else if (c->frequency < 470000000)
                bs = 0x02;
-       else if (params->frequency < 600000000)
+       else if (c->frequency < 600000000)
                bs = 0x08;
-       else if (params->frequency < 730000000)
+       else if (c->frequency < 730000000)
                bs = 0x08;
        else
                bs = 0x08;
@@ -461,25 +465,26 @@ static struct or51211_config or51211_config = {
        .sleep = or51211_sleep,
 };
 
-static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
 
-       div = (params->frequency + 36166667) / 166667;
+       div = (c->frequency + 36166667) / 166667;
 
        buf[0] = (div >> 8) & 0x7F;
        buf[1] = div & 0xFF;
        buf[2] = 0x85;
-       if ((params->frequency >= 47000000) && (params->frequency < 153000000))
+       if ((c->frequency >= 47000000) && (c->frequency < 153000000))
                buf[3] = 0x01;
-       else if ((params->frequency >= 153000000) && (params->frequency < 430000000))
+       else if ((c->frequency >= 153000000) && (c->frequency < 430000000))
                buf[3] = 0x02;
-       else if ((params->frequency >= 430000000) && (params->frequency < 824000000))
+       else if ((c->frequency >= 430000000) && (c->frequency < 824000000))
                buf[3] = 0x0C;
-       else if ((params->frequency >= 824000000) && (params->frequency < 863000000))
+       else if ((c->frequency >= 824000000) && (c->frequency < 863000000))
                buf[3] = 0x8C;
        else
                return -EINVAL;
@@ -513,31 +518,31 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend *fe,  u8 *pllbuf, int buf_len)
 {
        u32 div;
-       struct dvb_ofdm_parameters *op = &params->u.ofdm;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
        if (buf_len < 5)
                return -EINVAL;
 
-       div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+       div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
        pllbuf[0] = 0x61;
        pllbuf[1] = (div >> 8) & 0x7F;
        pllbuf[2] = div & 0xFF;
        pllbuf[3] = 0x85;
 
-       dprintk("frequency %u, div %u\n", params->frequency, div);
+       dprintk("frequency %u, div %u\n", c->frequency, div);
 
-       if (params->frequency < 470000000)
+       if (c->frequency < 470000000)
                pllbuf[4] = 0x02;
-       else if (params->frequency > 823000000)
+       else if (c->frequency > 823000000)
                pllbuf[4] = 0x88;
        else
                pllbuf[4] = 0x08;
 
-       if (op->bandwidth == 8)
+       if (c->bandwidth_hz == 8000000)
                pllbuf[4] |= 0x04;
 
        return 5;
@@ -663,7 +668,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                /*      DST is not a frontend driver !!!                */
                state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
                if (!state) {
-                       printk("dvb_bt8xx: No memory\n");
+                       pr_err("No memory\n");
                        break;
                }
                /*      Setup the Card                                  */
@@ -673,7 +678,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", __func__);
+                       pr_err("%s: Could not find a Twinhan DST\n", __func__);
                        break;
                }
                /*      Attach other DST peripherals if any             */
@@ -702,14 +707,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        }
 
        if (card->fe == NULL)
-               printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
+               pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       card->bt->dev->vendor,
                       card->bt->dev->device,
                       card->bt->dev->subsystem_vendor,
                       card->bt->dev->subsystem_device);
        else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
-                       printk("dvb-bt8xx: Frontend registration failed!\n");
+                       pr_err("Frontend registration failed!\n");
                        dvb_frontend_detach(card->fe);
                        card->fe = NULL;
                }
@@ -723,7 +728,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
                                      THIS_MODULE, &card->bt->dev->dev,
                                      adapter_nr);
        if (result < 0) {
-               printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
+               pr_err("dvb_register_adapter failed (errno = %d)\n", result);
                return result;
        }
        card->dvb_adapter.priv = card;
@@ -741,66 +746,69 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
        card->demux.stop_feed = dvb_bt8xx_stop_feed;
        card->demux.write_to_decoder = NULL;
 
-       if ((result = dvb_dmx_init(&card->demux)) < 0) {
-               printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
-               dvb_unregister_adapter(&card->dvb_adapter);
-               return result;
+       result = dvb_dmx_init(&card->demux);
+       if (result < 0) {
+               pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+               goto err_unregister_adaptor;
        }
 
        card->dmxdev.filternum = 256;
        card->dmxdev.demux = &card->demux.dmx;
        card->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) {
-               printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
-
-               dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(&card->dvb_adapter);
-               return result;
+       result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter);
+       if (result < 0) {
+               pr_err("dvb_dmxdev_init failed (errno = %d)\n", result);
+               goto err_dmx_release;
        }
 
        card->fe_hw.source = DMX_FRONTEND_0;
 
-       if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
-               printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
-               dvb_dmxdev_release(&card->dmxdev);
-               dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(&card->dvb_adapter);
-               return result;
+       result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw);
+       if (result < 0) {
+               pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+               goto err_dmxdev_release;
        }
 
        card->fe_mem.source = DMX_MEMORY_FE;
 
-       if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {
-               printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
-               card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
-               dvb_dmxdev_release(&card->dmxdev);
-               dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(&card->dvb_adapter);
-               return result;
+       result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem);
+       if (result < 0) {
+               pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+               goto err_remove_hw_frontend;
        }
 
-       if ((result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
-               printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
-               card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
-               card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
-               dvb_dmxdev_release(&card->dmxdev);
-               dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(&card->dvb_adapter);
-               return result;
+       result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw);
+       if (result < 0) {
+               pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+               goto err_remove_mem_frontend;
        }
 
-       dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+       result = dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+       if (result < 0) {
+               pr_err("dvb_net_init failed (errno = %d)\n", result);
+               goto err_disconnect_frontend;
+       }
 
        tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
 
        frontend_init(card, type);
 
        return 0;
+
+err_disconnect_frontend:
+       card->demux.dmx.disconnect_frontend(&card->demux.dmx);
+err_remove_mem_frontend:
+       card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+err_remove_hw_frontend:
+       card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+err_dmxdev_release:
+       dvb_dmxdev_release(&card->dmxdev);
+err_dmx_release:
+       dvb_dmx_release(&card->demux);
+err_unregister_adaptor:
+       dvb_unregister_adapter(&card->dvb_adapter);
+       return result;
 }
 
 static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
@@ -881,8 +889,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
                break;
 
        default:
-               printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n",
-                               sub->core->type);
+               pr_err("Unknown bttv card type: %d\n", sub->core->type);
                kfree(card);
                return -ENODEV;
        }
@@ -890,16 +897,14 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
        dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
 
        if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
-               printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
+               pr_err("no pci device for card %d\n", card->bttv_nr);
                kfree(card);
                return -ENODEV;
        }
 
        if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
-               printk("dvb_bt8xx: unable to determine DMA core of card %d,\n",
-                      card->bttv_nr);
-               printk("dvb_bt8xx: if you have the ALSA bt87x audio driver "
-                      "installed, try removing it.\n");
+               pr_err("unable to determine DMA core of card %d,\n", card->bttv_nr);
+               pr_err("if you have the ALSA bt87x audio driver installed, try removing it.\n");
 
                kfree(card);
                return -ENODEV;
index d1e91bc80e78ac1e819663ac827d2c4302e38f3d..ce4f85849e7b1cc6114b05e1664dd2be71dc6e54 100644 (file)
@@ -580,7 +580,7 @@ static int demod_attach_drxk(struct ddb_input *input)
        memset(&config, 0, sizeof(config));
        config.adr = 0x29 + (input->nr & 1);
 
-       fe = input->fe = dvb_attach(drxk_attach, &config, i2c, &input->fe2);
+       fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
        if (!input->fe) {
                printk(KERN_ERR "No DRXK found!\n");
                return -ENODEV;
index 55e6533f15e9f5ed8d5a95991256a14208fc7dcb..a609b3a9b14695bfff2a3e53a387c241e4b38107 100644 (file)
@@ -1115,11 +1115,14 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
        if (ret < 0)
                goto err_remove_mem_frontend;
 
-       ret = frontend_init(dev);
+       ret = dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
        if (ret < 0)
                goto err_disconnect_frontend;
 
-       dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
+       ret = frontend_init(dev);
+       if (ret < 0)
+               goto err_dvb_net;
+
        dm1105_ir_init(dev);
 
        INIT_WORK(&dev->work, dm1105_dmx_buffer);
index 7ea517b7e18626fd5723c255cb0aee2a102970a8..9be65a3b931fc91bd71c8155d8ccdd1da94e63e3 100644 (file)
@@ -1306,6 +1306,10 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
        /* fragment the packets & store in the buffer */
        while (fragpos < count) {
                fraglen = ca->slot_info[slot].link_buf_size - 2;
+               if (fraglen < 0)
+                       break;
+               if (fraglen > HOST_LINK_BUF_SIZE - 2)
+                       fraglen = HOST_LINK_BUF_SIZE - 2;
                if ((count - fragpos) < fraglen)
                        fraglen = count - fragpos;
 
index 2c0acdb4d81144b00b1381742505d18f208addb2..b15db4fe347b9218ec8b9e348802f424abb5d72b 100644 (file)
@@ -25,6 +25,9 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
+/* Enables DVBv3 compatibility bits at the headers */
+#define __DVB_CORE__
+
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -105,7 +108,6 @@ struct dvb_frontend_private {
 
        /* thread/frontend values */
        struct dvb_device *dvbdev;
-       struct dvb_frontend_parameters parameters_in;
        struct dvb_frontend_parameters parameters_out;
        struct dvb_fe_events events;
        struct semaphore sem;
@@ -139,6 +141,62 @@ struct dvb_frontend_private {
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
+static int dtv_get_frontend(struct dvb_frontend *fe,
+                           struct dvb_frontend_parameters *p_out);
+
+static bool has_get_frontend(struct dvb_frontend *fe)
+{
+       return fe->ops.get_frontend;
+}
+
+/*
+ * Due to DVBv3 API calls, a delivery system should be mapped into one of
+ * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
+ * otherwise, a DVBv3 call will fail.
+ */
+enum dvbv3_emulation_type {
+       DVBV3_UNKNOWN,
+       DVBV3_QPSK,
+       DVBV3_QAM,
+       DVBV3_OFDM,
+       DVBV3_ATSC,
+};
+
+static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
+{
+       switch (delivery_system) {
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               return DVBV3_QAM;
+       case SYS_DVBS:
+       case SYS_DVBS2:
+       case SYS_TURBO:
+       case SYS_ISDBS:
+       case SYS_DSS:
+               return DVBV3_QPSK;
+       case SYS_DVBT:
+       case SYS_DVBT2:
+       case SYS_ISDBT:
+       case SYS_DMBTH:
+               return DVBV3_OFDM;
+       case SYS_ATSC:
+       case SYS_DVBC_ANNEX_B:
+               return DVBV3_ATSC;
+       case SYS_UNDEFINED:
+       case SYS_ISDBC:
+       case SYS_DVBH:
+       case SYS_DAB:
+       case SYS_ATSCMH:
+       default:
+               /*
+                * Doesn't know how to emulate those types and/or
+                * there's no frontend driver from this type yet
+                * with some emulation code, so, we're not sure yet how
+                * to handle them, or they're not compatible with a DVBv3 call.
+                */
+               return DVBV3_UNKNOWN;
+       }
+}
 
 static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 {
@@ -149,8 +207,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 
        dprintk ("%s\n", __func__);
 
-       if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
-               fe->ops.get_frontend(fe, &fepriv->parameters_out);
+       if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
+               dtv_get_frontend(fe, &fepriv->parameters_out);
 
        mutex_lock(&events->mtx);
 
@@ -277,12 +335,13 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
        int ready = 0;
        int fe_set_err = 0;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int original_inversion = fepriv->parameters_in.inversion;
-       u32 original_frequency = fepriv->parameters_in.frequency;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
+       int original_inversion = c->inversion;
+       u32 original_frequency = c->frequency;
 
        /* are we using autoinversion? */
        autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-                        (fepriv->parameters_in.inversion == INVERSION_AUTO));
+                        (c->inversion == INVERSION_AUTO));
 
        /* setup parameters correctly */
        while(!ready) {
@@ -348,19 +407,20 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
                fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
 
        /* set the frontend itself */
-       fepriv->parameters_in.frequency += fepriv->lnb_drift;
+       c->frequency += fepriv->lnb_drift;
        if (autoinversion)
-               fepriv->parameters_in.inversion = fepriv->inversion;
+               c->inversion = fepriv->inversion;
+       tmp = *c;
        if (fe->ops.set_frontend)
-               fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in);
-       fepriv->parameters_out = fepriv->parameters_in;
+               fe_set_err = fe->ops.set_frontend(fe);
+       *c = tmp;
        if (fe_set_err < 0) {
                fepriv->state = FESTATE_ERROR;
                return fe_set_err;
        }
 
-       fepriv->parameters_in.frequency = original_frequency;
-       fepriv->parameters_in.inversion = original_inversion;
+       c->frequency = original_frequency;
+       c->inversion = original_inversion;
 
        fepriv->auto_sub_step++;
        return 0;
@@ -371,6 +431,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
        fe_status_t s = 0;
        int retval = 0;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
 
        /* if we've got no parameters, just keep idling */
        if (fepriv->state & FESTATE_IDLE) {
@@ -382,10 +443,10 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
        /* in SCAN mode, we just set the frontend when asked and leave it alone */
        if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
                if (fepriv->state & FESTATE_RETUNE) {
+                       tmp = *c;
                        if (fe->ops.set_frontend)
-                               retval = fe->ops.set_frontend(fe,
-                                                       &fepriv->parameters_in);
-                       fepriv->parameters_out = fepriv->parameters_in;
+                               retval = fe->ops.set_frontend(fe);
+                       *c = tmp;
                        if (retval < 0)
                                fepriv->state = FESTATE_ERROR;
                        else
@@ -415,8 +476,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 
                /* if we're tuned, then we have determined the correct inversion */
                if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-                   (fepriv->parameters_in.inversion == INVERSION_AUTO)) {
-                       fepriv->parameters_in.inversion = fepriv->inversion;
+                   (c->inversion == INVERSION_AUTO)) {
+                       c->inversion = fepriv->inversion;
                }
                return;
        }
@@ -507,7 +568,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
                return 1;
 
        if (fepriv->dvbdev->writers == 1)
-               if (time_after(jiffies, fepriv->release_jiffies +
+               if (time_after_eq(jiffies, fepriv->release_jiffies +
                                  dvb_shutdown_timeout * HZ))
                        return 1;
 
@@ -540,7 +601,7 @@ static int dvb_frontend_thread(void *data)
        fe_status_t s;
        enum dvbfe_algo algo;
 
-       struct dvb_frontend_parameters *params;
+       bool re_tune = false;
 
        dprintk("%s\n", __func__);
 
@@ -589,18 +650,15 @@ restart:
                        switch (algo) {
                        case DVBFE_ALGO_HW:
                                dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
-                               params = NULL; /* have we been asked to RETUNE ? */
 
                                if (fepriv->state & FESTATE_RETUNE) {
                                        dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
-                                       params = &fepriv->parameters_in;
+                                       re_tune = true;
                                        fepriv->state = FESTATE_TUNED;
                                }
 
                                if (fe->ops.tune)
-                                       fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
-                               if (params)
-                                       fepriv->parameters_out = *params;
+                                       fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s);
 
                                if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
                                        dprintk("%s: state changed, adding current state\n", __func__);
@@ -624,7 +682,7 @@ restart:
                                 */
                                if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
                                        if (fe->ops.search) {
-                                               fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in);
+                                               fepriv->algo_status = fe->ops.search(fe);
                                                /* We did do a search as was requested, the flags are
                                                 * now unset as well and has the flags wrt to search.
                                                 */
@@ -633,14 +691,10 @@ restart:
                                        }
                                }
                                /* Track the carrier if the search was successful */
-                               if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
-                                       if (fe->ops.track)
-                                               fe->ops.track(fe, &fepriv->parameters_in);
-                               } else {
+                               if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) {
                                        fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
                                        fepriv->delay = HZ / 2;
                                }
-                               fepriv->parameters_out = fepriv->parameters_in;
                                fe->ops.read_status(fe, &s);
                                if (s != fepriv->status) {
                                        dvb_frontend_add_event(fe, s); /* update event list */
@@ -807,52 +861,40 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
                       fe->dvb->num,fe->id);
 }
 
-static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *parms)
+static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 freq_min;
        u32 freq_max;
 
        /* range check: frequency */
        dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
-       if ((freq_min && parms->frequency < freq_min) ||
-           (freq_max && parms->frequency > freq_max)) {
+       if ((freq_min && c->frequency < freq_min) ||
+           (freq_max && c->frequency > freq_max)) {
                printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
-                      fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max);
+                      fe->dvb->num, fe->id, c->frequency, freq_min, freq_max);
                return -EINVAL;
        }
 
        /* range check: symbol rate */
-       if (fe->ops.info.type == FE_QPSK) {
-               if ((fe->ops.info.symbol_rate_min &&
-                    parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
-                   (fe->ops.info.symbol_rate_max &&
-                    parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) {
-                       printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
-                              fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate,
-                              fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
-                       return -EINVAL;
-               }
-
-       } else if (fe->ops.info.type == FE_QAM) {
+       switch (c->delivery_system) {
+       case SYS_DVBS:
+       case SYS_DVBS2:
+       case SYS_TURBO:
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
                if ((fe->ops.info.symbol_rate_min &&
-                    parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
+                    c->symbol_rate < fe->ops.info.symbol_rate_min) ||
                    (fe->ops.info.symbol_rate_max &&
-                    parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) {
+                    c->symbol_rate > fe->ops.info.symbol_rate_max)) {
                        printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
-                              fe->dvb->num, fe->id, parms->u.qam.symbol_rate,
-                              fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
+                              fe->dvb->num, fe->id, c->symbol_rate,
+                              fe->ops.info.symbol_rate_min,
+                              fe->ops.info.symbol_rate_max);
                        return -EINVAL;
                }
-       }
-
-       /* check for supported modulation */
-       if (fe->ops.info.type == FE_QAM &&
-           (parms->u.qam.modulation > QAM_AUTO ||
-            !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) {
-               printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n",
-                      fe->dvb->num, fe->id, parms->u.qam.modulation);
-                       return -EINVAL;
+       default:
+               break;
        }
 
        return 0;
@@ -866,28 +908,52 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
        memset(c, 0, sizeof(struct dtv_frontend_properties));
 
        c->state = DTV_CLEAR;
-       c->delivery_system = SYS_UNDEFINED;
-       c->inversion = INVERSION_AUTO;
-       c->fec_inner = FEC_AUTO;
+
+       dprintk("%s() Clearing cache for delivery system %d\n", __func__,
+               c->delivery_system);
+
        c->transmission_mode = TRANSMISSION_MODE_AUTO;
-       c->bandwidth_hz = BANDWIDTH_AUTO;
+       c->bandwidth_hz = 0;    /* AUTO */
        c->guard_interval = GUARD_INTERVAL_AUTO;
        c->hierarchy = HIERARCHY_AUTO;
-       c->symbol_rate = QAM_AUTO;
+       c->symbol_rate = 0;
        c->code_rate_HP = FEC_AUTO;
        c->code_rate_LP = FEC_AUTO;
-
-       c->isdbt_partial_reception = -1;
-       c->isdbt_sb_mode = -1;
-       c->isdbt_sb_subchannel = -1;
-       c->isdbt_sb_segment_idx = -1;
-       c->isdbt_sb_segment_count = -1;
-       c->isdbt_layer_enabled = 0x7;
+       c->fec_inner = FEC_AUTO;
+       c->rolloff = ROLLOFF_AUTO;
+       c->voltage = SEC_VOLTAGE_OFF;
+       c->sectone = SEC_TONE_OFF;
+       c->pilot = PILOT_AUTO;
+
+       c->isdbt_partial_reception = 0;
+       c->isdbt_sb_mode = 0;
+       c->isdbt_sb_subchannel = 0;
+       c->isdbt_sb_segment_idx = 0;
+       c->isdbt_sb_segment_count = 0;
+       c->isdbt_layer_enabled = 0;
        for (i = 0; i < 3; i++) {
                c->layer[i].fec = FEC_AUTO;
                c->layer[i].modulation = QAM_AUTO;
-               c->layer[i].interleaving = -1;
-               c->layer[i].segment_count = -1;
+               c->layer[i].interleaving = 0;
+               c->layer[i].segment_count = 0;
+       }
+
+       c->isdbs_ts_id = 0;
+       c->dvbt2_plp_id = 0;
+
+       switch (c->delivery_system) {
+       case SYS_DVBS:
+       case SYS_DVBS2:
+       case SYS_TURBO:
+               c->modulation = QPSK;   /* implied for DVB-S in legacy API */
+               c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+               break;
+       case SYS_ATSC:
+               c->modulation = VSB_8;
+               break;
+       default:
+               c->modulation = QAM_AUTO;
+               break;
        }
 
        return 0;
@@ -973,6 +1039,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
        _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
        _DTV_CMD(DTV_HIERARCHY, 0, 0),
+
+       _DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
 };
 
 static void dtv_property_dump(struct dtv_property *tvp)
@@ -1006,70 +1074,54 @@ static void dtv_property_dump(struct dtv_property *tvp)
                dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
 }
 
-static int is_legacy_delivery_system(fe_delivery_system_t s)
-{
-       if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
-          (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
-          (s == SYS_ATSC))
-               return 1;
-
-       return 0;
-}
-
-/* Initialize the cache with some default values derived from the
- * legacy frontend_info structure.
- */
-static void dtv_property_cache_init(struct dvb_frontend *fe,
-                                   struct dtv_frontend_properties *c)
-{
-       switch (fe->ops.info.type) {
-       case FE_QPSK:
-               c->modulation = QPSK;   /* implied for DVB-S in legacy API */
-               c->rolloff = ROLLOFF_35;/* implied for DVB-S */
-               c->delivery_system = SYS_DVBS;
-               break;
-       case FE_QAM:
-               c->delivery_system = SYS_DVBC_ANNEX_AC;
-               break;
-       case FE_OFDM:
-               c->delivery_system = SYS_DVBT;
-               break;
-       case FE_ATSC:
-               break;
-       }
-}
-
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
  * drivers can use a single set_frontend tuning function, regardless of whether
  * it's being used for the legacy or new API, reducing code and complexity.
  */
-static void dtv_property_cache_sync(struct dvb_frontend *fe,
-                                   struct dtv_frontend_properties *c,
-                                   const struct dvb_frontend_parameters *p)
+static int dtv_property_cache_sync(struct dvb_frontend *fe,
+                                  struct dtv_frontend_properties *c,
+                                  const struct dvb_frontend_parameters *p)
 {
        c->frequency = p->frequency;
        c->inversion = p->inversion;
 
-       switch (fe->ops.info.type) {
-       case FE_QPSK:
+       switch (dvbv3_type(c->delivery_system)) {
+       case DVBV3_QPSK:
+               dprintk("%s() Preparing QPSK req\n", __func__);
                c->symbol_rate = p->u.qpsk.symbol_rate;
                c->fec_inner = p->u.qpsk.fec_inner;
                break;
-       case FE_QAM:
+       case DVBV3_QAM:
+               dprintk("%s() Preparing QAM req\n", __func__);
                c->symbol_rate = p->u.qam.symbol_rate;
                c->fec_inner = p->u.qam.fec_inner;
                c->modulation = p->u.qam.modulation;
                break;
-       case FE_OFDM:
-               if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
-                       c->bandwidth_hz = 6000000;
-               else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
-                       c->bandwidth_hz = 7000000;
-               else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+       case DVBV3_OFDM:
+               dprintk("%s() Preparing OFDM req\n", __func__);
+               switch (p->u.ofdm.bandwidth) {
+               case BANDWIDTH_10_MHZ:
+                       c->bandwidth_hz = 10000000;
+                       break;
+               case BANDWIDTH_8_MHZ:
                        c->bandwidth_hz = 8000000;
-               else
-                       /* Including BANDWIDTH_AUTO */
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       c->bandwidth_hz = 7000000;
+                       break;
+               case BANDWIDTH_6_MHZ:
+                       c->bandwidth_hz = 6000000;
+                       break;
+               case BANDWIDTH_5_MHZ:
+                       c->bandwidth_hz = 5000000;
+                       break;
+               case BANDWIDTH_1_712_MHZ:
+                       c->bandwidth_hz = 1712000;
+                       break;
+               case BANDWIDTH_AUTO:
                        c->bandwidth_hz = 0;
+               }
+
                c->code_rate_HP = p->u.ofdm.code_rate_HP;
                c->code_rate_LP = p->u.ofdm.code_rate_LP;
                c->modulation = p->u.ofdm.constellation;
@@ -1077,50 +1129,78 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
                c->guard_interval = p->u.ofdm.guard_interval;
                c->hierarchy = p->u.ofdm.hierarchy_information;
                break;
-       case FE_ATSC:
+       case DVBV3_ATSC:
+               dprintk("%s() Preparing ATSC req\n", __func__);
                c->modulation = p->u.vsb.modulation;
                if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
                        c->delivery_system = SYS_ATSC;
                else
                        c->delivery_system = SYS_DVBC_ANNEX_B;
                break;
+       case DVBV3_UNKNOWN:
+               printk(KERN_ERR
+                      "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                      __func__, c->delivery_system);
+               return -EINVAL;
        }
+
+       return 0;
 }
 
 /* Ensure the cached values are set correctly in the frontend
  * legacy tuning structures, for the advanced tuning API.
  */
-static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+                                           struct dvb_frontend_parameters *p)
 {
        const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       struct dvb_frontend_parameters *p = &fepriv->parameters_in;
 
        p->frequency = c->frequency;
        p->inversion = c->inversion;
 
-       switch (fe->ops.info.type) {
-       case FE_QPSK:
+       switch (dvbv3_type(c->delivery_system)) {
+       case DVBV3_UNKNOWN:
+               printk(KERN_ERR
+                      "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                      __func__, c->delivery_system);
+               return -EINVAL;
+       case DVBV3_QPSK:
                dprintk("%s() Preparing QPSK req\n", __func__);
                p->u.qpsk.symbol_rate = c->symbol_rate;
                p->u.qpsk.fec_inner = c->fec_inner;
                break;
-       case FE_QAM:
+       case DVBV3_QAM:
                dprintk("%s() Preparing QAM req\n", __func__);
                p->u.qam.symbol_rate = c->symbol_rate;
                p->u.qam.fec_inner = c->fec_inner;
                p->u.qam.modulation = c->modulation;
                break;
-       case FE_OFDM:
+       case DVBV3_OFDM:
                dprintk("%s() Preparing OFDM req\n", __func__);
-               if (c->bandwidth_hz == 6000000)
-                       p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
-               else if (c->bandwidth_hz == 7000000)
-                       p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
-               else if (c->bandwidth_hz == 8000000)
+
+               switch (c->bandwidth_hz) {
+               case 10000000:
+                       p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ;
+                       break;
+               case 8000000:
                        p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
-               else
+                       break;
+               case 7000000:
+                       p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+                       break;
+               case 6000000:
+                       p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+                       break;
+               case 5000000:
+                       p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ;
+                       break;
+               case 1712000:
+                       p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ;
+                       break;
+               case 0:
+               default:
                        p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+               }
                p->u.ofdm.code_rate_HP = c->code_rate_HP;
                p->u.ofdm.code_rate_LP = c->code_rate_LP;
                p->u.ofdm.constellation = c->modulation;
@@ -1128,78 +1208,40 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
                p->u.ofdm.guard_interval = c->guard_interval;
                p->u.ofdm.hierarchy_information = c->hierarchy;
                break;
-       case FE_ATSC:
+       case DVBV3_ATSC:
                dprintk("%s() Preparing VSB req\n", __func__);
                p->u.vsb.modulation = c->modulation;
                break;
        }
+       return 0;
 }
 
-/* Ensure the cached values are set correctly in the frontend
- * legacy tuning structures, for the legacy tuning API.
+/**
+ * dtv_get_frontend - calls a callback for retrieving DTV parameters
+ * @fe:                struct dvb_frontend pointer
+ * @c:         struct dtv_frontend_properties pointer (DVBv5 cache)
+ * @p_out      struct dvb_frontend_parameters pointer (DVBv3 FE struct)
+ *
+ * This routine calls either the DVBv3 or DVBv5 get_frontend call.
+ * If c is not null, it will update the DVBv5 cache struct pointed by it.
+ * If p_out is not null, it will update the DVBv3 params pointed by it.
  */
-static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
+static int dtv_get_frontend(struct dvb_frontend *fe,
+                           struct dvb_frontend_parameters *p_out)
 {
-       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       struct dvb_frontend_parameters *p = &fepriv->parameters_in;
-
-       p->frequency = c->frequency;
-       p->inversion = c->inversion;
-
-       if (c->delivery_system == SYS_DSS ||
-           c->delivery_system == SYS_DVBS ||
-           c->delivery_system == SYS_DVBS2 ||
-           c->delivery_system == SYS_ISDBS ||
-           c->delivery_system == SYS_TURBO) {
-               p->u.qpsk.symbol_rate = c->symbol_rate;
-               p->u.qpsk.fec_inner = c->fec_inner;
-       }
+       int r;
 
-       /* Fake out a generic DVB-T request so we pass validation in the ioctl */
-       if ((c->delivery_system == SYS_ISDBT) ||
-           (c->delivery_system == SYS_DVBT2)) {
-               p->u.ofdm.constellation = QAM_AUTO;
-               p->u.ofdm.code_rate_HP = FEC_AUTO;
-               p->u.ofdm.code_rate_LP = FEC_AUTO;
-               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
-               p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
-               p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
-               if (c->bandwidth_hz == 8000000)
-                       p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
-               else if (c->bandwidth_hz == 7000000)
-                       p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
-               else if (c->bandwidth_hz == 6000000)
-                       p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
-               else
-                       p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+       if (fe->ops.get_frontend) {
+               r = fe->ops.get_frontend(fe);
+               if (unlikely(r < 0))
+                       return r;
+               if (p_out)
+                       dtv_property_legacy_params_sync(fe, p_out);
+               return 0;
        }
-}
-
-static void dtv_property_cache_submit(struct dvb_frontend *fe)
-{
-       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-       /* For legacy delivery systems we don't need the delivery_system to
-        * be specified, but we populate the older structures from the cache
-        * so we can call set_frontend on older drivers.
-        */
-       if(is_legacy_delivery_system(c->delivery_system)) {
-
-               dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation);
-               dtv_property_legacy_params_sync(fe);
-
-       } else {
-               dprintk("%s() adv, modulation = %d\n", __func__, c->modulation);
-
-               /* For advanced delivery systems / modulation types ...
-                * we seed the lecacy dvb_frontend_parameters structure
-                * so that the sanity checking code later in the IOCTL processing
-                * can validate our basic frequency ranges, symbolrates, modulation
-                * etc.
-                */
-               dtv_property_adv_params_sync(fe);
-       }
+       /* As everything is in cache, get_frontend fops are always supported */
+       return 0;
 }
 
 static int dvb_frontend_ioctl_legacy(struct file *file,
@@ -1208,25 +1250,21 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                        unsigned int cmd, void *parg);
 
 static int dtv_property_process_get(struct dvb_frontend *fe,
+                                   const struct dtv_frontend_properties *c,
                                    struct dtv_property *tvp,
                                    struct file *file)
 {
-       const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       struct dtv_frontend_properties cdetected;
-       int r;
-
-       /*
-        * If the driver implements a get_frontend function, then convert
-        * detected parameters to S2API properties.
-        */
-       if (fe->ops.get_frontend) {
-               cdetected = *c;
-               dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out);
-               c = &cdetected;
-       }
+       int r, ncaps;
 
        switch(tvp->cmd) {
+       case DTV_ENUM_DELSYS:
+               ncaps = 0;
+               while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+                       tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
+                       ncaps++;
+               }
+               tvp->u.buffer.len = ncaps;
+               break;
        case DTV_FREQUENCY:
                tvp->u.data = c->frequency;
                break;
@@ -1356,14 +1394,159 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
        return 0;
 }
 
+static int dtv_set_frontend(struct dvb_frontend *fe);
+
+static bool is_dvbv3_delsys(u32 delsys)
+{
+       bool status;
+
+       status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
+                (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
+
+       return status;
+}
+
+static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
+{
+       int ncaps, i;
+       u32 delsys = SYS_UNDEFINED;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       enum dvbv3_emulation_type type;
+
+       if (desired_system == SYS_UNDEFINED) {
+               /*
+                * A DVBv3 call doesn't know what's the desired system.
+                * Also, DVBv3 applications don't know that ops.info->type
+                * could be changed, and they simply dies when it doesn't
+                * match.
+                * So, don't change the current delivery system, as it
+                * may be trying to do the wrong thing, like setting an
+                * ISDB-T frontend as DVB-T. Instead, find the closest
+                * DVBv3 system that matches the delivery system.
+                */
+               if (is_dvbv3_delsys(c->delivery_system)) {
+                       dprintk("%s() Using delivery system to %d\n",
+                               __func__, c->delivery_system);
+                       return 0;
+               }
+               type = dvbv3_type(c->delivery_system);
+               switch (type) {
+               case DVBV3_QPSK:
+                       desired_system = SYS_DVBS;
+                       break;
+               case DVBV3_QAM:
+                       desired_system = SYS_DVBC_ANNEX_A;
+                       break;
+               case DVBV3_ATSC:
+                       desired_system = SYS_ATSC;
+                       break;
+               case DVBV3_OFDM:
+                       desired_system = SYS_DVBT;
+                       break;
+               default:
+                       dprintk("%s(): This frontend doesn't support DVBv3 calls\n",
+                               __func__);
+                       return -EINVAL;
+               }
+       } else {
+               /*
+                * This is a DVBv5 call. So, it likely knows the supported
+                * delivery systems.
+                */
+
+               /* Check if the desired delivery system is supported */
+               ncaps = 0;
+               while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+                       if (fe->ops.delsys[ncaps] == desired_system) {
+                               c->delivery_system = desired_system;
+                               dprintk("%s() Changing delivery system to %d\n",
+                                       __func__, desired_system);
+                               return 0;
+                       }
+                       ncaps++;
+               }
+               type = dvbv3_type(desired_system);
+
+               /*
+                * The delivery system is not supported. See if it can be
+                * emulated.
+                * The emulation only works if the desired system is one of the
+                * DVBv3 delivery systems
+                */
+               if (!is_dvbv3_delsys(desired_system)) {
+                       dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
+                               __func__);
+                       return -EINVAL;
+               }
+
+               /*
+                * Get the last non-DVBv3 delivery system that has the same type
+                * of the desired system
+                */
+               ncaps = 0;
+               while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+                       if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
+                           !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
+                               delsys = fe->ops.delsys[ncaps];
+                       ncaps++;
+               }
+               /* There's nothing compatible with the desired delivery system */
+               if (delsys == SYS_UNDEFINED) {
+                       dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
+                               __func__);
+                       return -EINVAL;
+               }
+               c->delivery_system = delsys;
+       }
+
+       /*
+        * The DVBv3 or DVBv5 call is requesting a different system. So,
+        * emulation is needed.
+        *
+        * Emulate newer delivery systems like ISDBT, DVBT and DMBTH
+        * for older DVBv5 applications. The emulation will try to use
+        * the auto mode for most things, and will assume that the desired
+        * delivery system is the last one at the ops.delsys[] array
+        */
+       dprintk("%s() Using delivery system %d emulated as if it were a %d\n",
+               __func__, delsys, desired_system);
+
+       /*
+        * For now, handles ISDB-T calls. More code may be needed here for the
+        * other emulated stuff
+        */
+       if (type == DVBV3_OFDM) {
+               if (c->delivery_system == SYS_ISDBT) {
+                       dprintk("%s() Using defaults for SYS_ISDBT\n",
+                               __func__);
+                       if (!c->bandwidth_hz)
+                               c->bandwidth_hz = 6000000;
+
+                       c->isdbt_partial_reception = 0;
+                       c->isdbt_sb_mode = 0;
+                       c->isdbt_sb_subchannel = 0;
+                       c->isdbt_sb_segment_idx = 0;
+                       c->isdbt_sb_segment_count = 0;
+                       c->isdbt_layer_enabled = 0;
+                       for (i = 0; i < 3; i++) {
+                               c->layer[i].fec = FEC_AUTO;
+                               c->layer[i].modulation = QAM_AUTO;
+                               c->layer[i].interleaving = 0;
+                               c->layer[i].segment_count = 0;
+                       }
+               }
+       }
+       dprintk("change delivery system on cache to %d\n", c->delivery_system);
+
+       return 0;
+}
+
 static int dtv_property_process_set(struct dvb_frontend *fe,
                                    struct dtv_property *tvp,
                                    struct file *file)
 {
        int r = 0;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       dtv_property_dump(tvp);
 
        /* Allow the frontend to validate incoming properties */
        if (fe->ops.set_property) {
@@ -1374,11 +1557,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 
        switch(tvp->cmd) {
        case DTV_CLEAR:
-               /* Reset a cache of data specific to the frontend here. This does
+               /*
+                * Reset a cache of data specific to the frontend here. This does
                 * not effect hardware.
                 */
                dvb_frontend_clear_cache(fe);
-               dprintk("%s() Flushing property cache\n", __func__);
                break;
        case DTV_TUNE:
                /* interpret the cache of data, build either a traditional frontend
@@ -1387,10 +1570,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                 */
                c->state = tvp->cmd;
                dprintk("%s() Finalised property cache\n", __func__);
-               dtv_property_cache_submit(fe);
 
-               r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
-                       &fepriv->parameters_in);
+               r = dtv_set_frontend(fe);
                break;
        case DTV_FREQUENCY:
                c->frequency = tvp->u.data;
@@ -1417,7 +1598,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                c->rolloff = tvp->u.data;
                break;
        case DTV_DELIVERY_SYSTEM:
-               c->delivery_system = tvp->u.data;
+               r = set_delivery_system(fe, tvp->u.data);
                break;
        case DTV_VOLTAGE:
                c->voltage = tvp->u.data;
@@ -1594,7 +1775,6 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 
        } else
        if(cmd == FE_GET_PROPERTY) {
-
                tvps = (struct dtv_properties __user *)parg;
 
                dprintk("%s() properties.num = %d\n", __func__, tvps->num);
@@ -1616,8 +1796,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                        goto out;
                }
 
+               /*
+                * Fills the cache out struct with the cache contents, plus
+                * the data retrieved from get_frontend.
+                */
+               dtv_get_frontend(fe, NULL);
                for (i = 0; i < tvps->num; i++) {
-                       err = dtv_property_process_get(fe, tvp + i, file);
+                       err = dtv_property_process_get(fe, c, tvp + i, file);
                        if (err < 0)
                                goto out;
                        (tvp + i)->result = err;
@@ -1636,12 +1821,121 @@ out:
        return err;
 }
 
+static int dtv_set_frontend(struct dvb_frontend *fe)
+{
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct dvb_frontend_tune_settings fetunesettings;
+       u32 rolloff = 0;
+
+       if (dvb_frontend_check_parameters(fe) < 0)
+               return -EINVAL;
+
+       /*
+        * Be sure that the bandwidth will be filled for all
+        * non-satellite systems, as tuners need to know what
+        * low pass/Nyquist half filter should be applied, in
+        * order to avoid inter-channel noise.
+        *
+        * ISDB-T and DVB-T/T2 already sets bandwidth.
+        * ATSC and DVB-C don't set, so, the core should fill it.
+        *
+        * On DVB-C Annex A and C, the bandwidth is a function of
+        * the roll-off and symbol rate. Annex B defines different
+        * roll-off factors depending on the modulation. Fortunately,
+        * Annex B is only used with 6MHz, so there's no need to
+        * calculate it.
+        *
+        * While not officially supported, a side effect of handling it at
+        * the cache level is that a program could retrieve the bandwidth
+        * via DTV_BANDWIDTH_HZ, which may be useful for test programs.
+        */
+       switch (c->delivery_system) {
+       case SYS_ATSC:
+       case SYS_DVBC_ANNEX_B:
+               c->bandwidth_hz = 6000000;
+               break;
+       case SYS_DVBC_ANNEX_A:
+               rolloff = 115;
+               break;
+       case SYS_DVBC_ANNEX_C:
+               rolloff = 113;
+               break;
+       default:
+               break;
+       }
+       if (rolloff)
+               c->bandwidth_hz = (c->symbol_rate * rolloff) / 100;
+
+       /* force auto frequency inversion if requested */
+       if (dvb_force_auto_inversion)
+               c->inversion = INVERSION_AUTO;
+
+       /*
+        * without hierarchical coding code_rate_LP is irrelevant,
+        * so we tolerate the otherwise invalid FEC_NONE setting
+        */
+       if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
+               c->code_rate_LP = FEC_AUTO;
+
+       /* get frontend-specific tuning settings */
+       memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+       if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+               fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+               fepriv->max_drift = fetunesettings.max_drift;
+               fepriv->step_size = fetunesettings.step_size;
+       } else {
+               /* default values */
+               switch (c->delivery_system) {
+               case SYS_DVBC_ANNEX_A:
+               case SYS_DVBC_ANNEX_C:
+                       fepriv->min_delay = HZ / 20;
+                       fepriv->step_size = c->symbol_rate / 16000;
+                       fepriv->max_drift = c->symbol_rate / 2000;
+                       break;
+               case SYS_DVBT:
+               case SYS_DVBT2:
+               case SYS_ISDBT:
+               case SYS_DMBTH:
+                       fepriv->min_delay = HZ / 20;
+                       fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+                       fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+                       break;
+               default:
+                       /*
+                        * FIXME: This sounds wrong! if freqency_stepsize is
+                        * defined by the frontend, why not use it???
+                        */
+                       fepriv->min_delay = HZ / 20;
+                       fepriv->step_size = 0; /* no zigzag */
+                       fepriv->max_drift = 0;
+                       break;
+               }
+       }
+       if (dvb_override_tune_delay > 0)
+               fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+       fepriv->state = FESTATE_RETUNE;
+
+       /* Request the search algorithm to search */
+       fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+       dvb_frontend_clear_events(fe);
+       dvb_frontend_add_event(fe, 0);
+       dvb_frontend_wakeup(fe);
+       fepriv->status = 0;
+
+       return 0;
+}
+
+
 static int dvb_frontend_ioctl_legacy(struct file *file,
                        unsigned int cmd, void *parg)
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int cb_err, err = -EOPNOTSUPP;
 
        if (fe->dvb->fe_ioctl_override) {
@@ -1658,9 +1952,43 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
        switch (cmd) {
        case FE_GET_INFO: {
                struct dvb_frontend_info* info = parg;
+
                memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
                dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
 
+               /*
+                * Associate the 4 delivery systems supported by DVBv3
+                * API with their DVBv5 counterpart. For the other standards,
+                * use the closest type, assuming that it would hopefully
+                * work with a DVBv3 application.
+                * It should be noticed that, on multi-frontend devices with
+                * different types (terrestrial and cable, for example),
+                * a pure DVBv3 application won't be able to use all delivery
+                * systems. Yet, changing the DVBv5 cache to the other delivery
+                * system should be enough for making it work.
+                */
+               switch (dvbv3_type(c->delivery_system)) {
+               case DVBV3_QPSK:
+                       info->type = FE_QPSK;
+                       break;
+               case DVBV3_ATSC:
+                       info->type = FE_ATSC;
+                       break;
+               case DVBV3_QAM:
+                       info->type = FE_QAM;
+                       break;
+               case DVBV3_OFDM:
+                       info->type = FE_OFDM;
+                       break;
+               default:
+                       printk(KERN_ERR
+                              "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                              __func__, c->delivery_system);
+                       fe->ops.info.type = FE_OFDM;
+               }
+               dprintk("current delivery system on cache: %d, V3 type: %d\n",
+                       c->delivery_system, fe->ops.info.type);
+
                /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
                 * do it, it is done for it. */
                info->caps |= FE_CAN_INVERSION_AUTO;
@@ -1819,108 +2147,22 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                        err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
                break;
 
-       case FE_SET_FRONTEND: {
-               struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-               struct dvb_frontend_tune_settings fetunesettings;
-
-               if (c->state == DTV_TUNE) {
-                       if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) {
-                               err = -EINVAL;
-                               break;
-                       }
-               } else {
-                       if (dvb_frontend_check_parameters(fe, parg) < 0) {
-                               err = -EINVAL;
-                               break;
-                       }
-
-                       memcpy (&fepriv->parameters_in, parg,
-                               sizeof (struct dvb_frontend_parameters));
-                       dtv_property_cache_init(fe, c);
-                       dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
-               }
-
-               /*
-                * Initialize output parameters to match the values given by
-                * the user. FE_SET_FRONTEND triggers an initial frontend event
-                * with status = 0, which copies output parameters to userspace.
-                */
-               fepriv->parameters_out = fepriv->parameters_in;
-
-               memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
-               memcpy(&fetunesettings.parameters, parg,
-                      sizeof (struct dvb_frontend_parameters));
-
-               /* force auto frequency inversion if requested */
-               if (dvb_force_auto_inversion) {
-                       fepriv->parameters_in.inversion = INVERSION_AUTO;
-                       fetunesettings.parameters.inversion = INVERSION_AUTO;
-               }
-               if (fe->ops.info.type == FE_OFDM) {
-                       /* without hierarchical coding code_rate_LP is irrelevant,
-                        * so we tolerate the otherwise invalid FEC_NONE setting */
-                       if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
-                           fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE)
-                               fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO;
-               }
-
-               /* get frontend-specific tuning settings */
-               if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
-                       fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
-                       fepriv->max_drift = fetunesettings.max_drift;
-                       fepriv->step_size = fetunesettings.step_size;
-               } else {
-                       /* default values */
-                       switch(fe->ops.info.type) {
-                       case FE_QPSK:
-                               fepriv->min_delay = HZ/20;
-                               fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000;
-                               fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000;
-                               break;
-
-                       case FE_QAM:
-                               fepriv->min_delay = HZ/20;
-                               fepriv->step_size = 0; /* no zigzag */
-                               fepriv->max_drift = 0;
-                               break;
-
-                       case FE_OFDM:
-                               fepriv->min_delay = HZ/20;
-                               fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
-                               fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-                               break;
-                       case FE_ATSC:
-                               fepriv->min_delay = HZ/20;
-                               fepriv->step_size = 0;
-                               fepriv->max_drift = 0;
-                               break;
-                       }
-               }
-               if (dvb_override_tune_delay > 0)
-                       fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
-
-               fepriv->state = FESTATE_RETUNE;
-
-               /* Request the search algorithm to search */
-               fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+       case FE_SET_FRONTEND:
+               err = set_delivery_system(fe, SYS_UNDEFINED);
+               if (err)
+                       break;
 
-               dvb_frontend_clear_events(fe);
-               dvb_frontend_add_event(fe, 0);
-               dvb_frontend_wakeup(fe);
-               fepriv->status = 0;
-               err = 0;
+               err = dtv_property_cache_sync(fe, c, parg);
+               if (err)
+                       break;
+               err = dtv_set_frontend(fe);
                break;
-       }
-
        case FE_GET_EVENT:
                err = dvb_frontend_get_event (fe, parg, file->f_flags);
                break;
 
        case FE_GET_FRONTEND:
-               if (fe->ops.get_frontend) {
-                       err = fe->ops.get_frontend(fe, &fepriv->parameters_out);
-                       memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters));
-               }
+               err = dtv_get_frontend(fe, parg);
                break;
 
        case FE_SET_FRONTEND_TUNE_MODE:
@@ -2061,12 +2303,15 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
 
        dprintk ("%s\n", __func__);
 
-       if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+       if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
                fepriv->release_jiffies = jiffies;
+               mb();
+       }
 
        ret = dvb_generic_release (inode, file);
 
        if (dvbdev->users == -1) {
+               wake_up(&fepriv->wait_queue);
                if (fepriv->exit != DVB_FE_NO_EXIT) {
                        fops_put(file->f_op);
                        file->f_op = NULL;
@@ -2127,6 +2372,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
        dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
                             fe, DVB_DEVICE_FRONTEND);
 
+       /*
+        * Initialize the cache to the proper values according with the
+        * first supported delivery system (ops->delsys[0])
+        */
+
+        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
+       dvb_frontend_clear_cache(fe);
+
        mutex_unlock(&frontend_mutex);
        return 0;
 }
index 67bbfa728016f72ef600bd683d84ef422930362e..d63a8215fe0315fa893902206a64f99303b9fb77 100644 (file)
 
 #include "dvbdev.h"
 
+/*
+ * Maximum number of Delivery systems per frontend. It
+ * should be smaller or equal to 32
+ */
+#define MAX_DELSYS     8
+
 struct dvb_frontend_tune_settings {
        int min_delay_ms;
        int step_size;
        int max_drift;
-       struct dvb_frontend_parameters parameters;
 };
 
 struct dvb_frontend;
@@ -198,11 +203,11 @@ struct dvb_tuner_ops {
        int (*sleep)(struct dvb_frontend *fe);
 
        /** This is for simple PLLs - set all parameters in one go. */
-       int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+       int (*set_params)(struct dvb_frontend *fe);
        int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
 
        /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
-       int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+       int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
 
        /** This is to allow setting tuner-specific configs */
        int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
@@ -250,10 +255,14 @@ struct analog_demod_ops {
        int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
 };
 
+struct dtv_frontend_properties;
+
 struct dvb_frontend_ops {
 
        struct dvb_frontend_info info;
 
+       u8 delsys[MAX_DELSYS];
+
        void (*release)(struct dvb_frontend* fe);
        void (*release_sec)(struct dvb_frontend* fe);
 
@@ -264,7 +273,7 @@ struct dvb_frontend_ops {
 
        /* if this is set, it overrides the default swzigzag */
        int (*tune)(struct dvb_frontend* fe,
-                   struct dvb_frontend_parameters* params,
+                   bool re_tune,
                    unsigned int mode_flags,
                    unsigned int *delay,
                    fe_status_t *status);
@@ -272,10 +281,10 @@ struct dvb_frontend_ops {
        enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
 
        /* these two are only used for the swzigzag code */
-       int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+       int (*set_frontend)(struct dvb_frontend *fe);
        int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
 
-       int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+       int (*get_frontend)(struct dvb_frontend *fe);
 
        int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
        int (*read_ber)(struct dvb_frontend* fe, u32* ber);
@@ -297,8 +306,7 @@ struct dvb_frontend_ops {
        /* These callbacks are for devices that implement their own
         * tuning algorithms, rather than a simple swzigzag
         */
-       enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
-       int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+       enum dvbfe_search (*search)(struct dvb_frontend *fe);
 
        struct dvb_tuner_ops tuner_ops;
        struct analog_demod_ops analog_ops;
@@ -307,6 +315,7 @@ struct dvb_frontend_ops {
        int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
 };
 
+#ifdef __DVB_CORE__
 #define MAX_EVENT 8
 
 struct dvb_fe_events {
@@ -317,6 +326,7 @@ struct dvb_fe_events {
        wait_queue_head_t         wait_queue;
        struct mutex              mtx;
 };
+#endif
 
 struct dtv_frontend_properties {
 
@@ -374,6 +384,7 @@ struct dvb_frontend {
        void *analog_demod_priv;
        struct dtv_frontend_properties dtv_property_cache;
 #define DVB_FRONTEND_COMPONENT_TUNER 0
+#define DVB_FRONTEND_COMPONENT_DEMOD 1
        int (*callback)(void *adapter_priv, int component, int cmd, int arg);
        int id;
 };
index 93d9869e0f15f3ecd10588a9bd981ab7a6ba8dfc..8766ce8c354dd908e1fbb9a493942e8669fe4259 100644 (file)
@@ -1510,9 +1510,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
        for (i=0; i<DVB_NET_DEVICES_MAX; i++)
                dvbnet->state[i] = 0;
 
-       dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net,
+       return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
                             dvbnet, DVB_DEVICE_NET);
-
-       return 0;
 }
 EXPORT_SYMBOL(dvb_net_init);
index 58257165761e1b016a58b30019a9388d395400b2..9f203c6767a672baf3405d6c6751a39e4e96fed8 100644 (file)
@@ -311,6 +311,7 @@ config DVB_USB_ANYSEE
        select DVB_STV0900 if !DVB_FE_CUSTOMISE
        select DVB_STV6110 if !DVB_FE_CUSTOMISE
        select DVB_ISL6423 if !DVB_FE_CUSTOMISE
+       select DVB_CXD2820R if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Anysee E30, Anysee E30 Plus or
          Anysee E30 C Plus DVB USB2.0 receiver.
@@ -340,7 +341,7 @@ config DVB_USB_AF9015
 
 config DVB_USB_CE6230
        tristate "Intel CE6230 DVB-T USB2.0 support"
-       depends on DVB_USB && EXPERIMENTAL
+       depends on DVB_USB
        select DVB_ZL10353
        select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
        help
@@ -354,7 +355,7 @@ config DVB_USB_FRIIO
 
 config DVB_USB_EC168
        tristate "E3C EC168 DVB-T USB2.0 support"
-       depends on DVB_USB && EXPERIMENTAL
+       depends on DVB_USB
        select DVB_EC100
        select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
        help
index 3263e9749d09dfd610e467da5a583f84c26dc2d1..740f3f496f12c171bfe19564eafaa69fdfa6f40d 100644 (file)
@@ -303,7 +303,7 @@ static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       /* read constellation mode */
+       /* read modulation mode */
        ret =
            af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
                                      reg_tpsd_const_pos, reg_tpsd_const_len,
@@ -321,7 +321,7 @@ static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
                bits = 6;
                break;
        default:
-               err("invalid constellation mode");
+               err("invalid modulation mode");
                return -EINVAL;
        }
        *pre_bit_count = super_frame_count * 68 * 4 * x * bits;
@@ -533,13 +533,13 @@ static int af9005_fe_read_signal_strength(struct dvb_frontend *fe,
 
 static int af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr)
 {
-       /* the snr can be derived from the ber and the constellation
+       /* the snr can be derived from the ber and the modulation
           but I don't think this kind of complex calculations belong
           in the driver. I may be wrong.... */
        return -ENOSYS;
 }
 
-static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
+static int af9005_fe_program_cfoe(struct dvb_usb_device *d, u32 bw)
 {
        u8 temp0, temp1, temp2, temp3, buf[4];
        int ret;
@@ -551,7 +551,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
        u32 NS_coeff2_8k;
 
        switch (bw) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                NS_coeff1_2048Nu = 0x2ADB6DC;
                NS_coeff1_8191Nu = 0xAB7313;
                NS_coeff1_8192Nu = 0xAB6DB7;
@@ -560,7 +560,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
                NS_coeff2_8k = 0x55B6DC;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                NS_coeff1_2048Nu = 0x3200001;
                NS_coeff1_8191Nu = 0xC80640;
                NS_coeff1_8192Nu = 0xC80000;
@@ -569,7 +569,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
                NS_coeff2_8k = 0x640000;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                NS_coeff1_2048Nu = 0x3924926;
                NS_coeff1_8191Nu = 0xE4996E;
                NS_coeff1_8192Nu = 0xE49249;
@@ -773,17 +773,17 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
 
 }
 
-static int af9005_fe_select_bw(struct dvb_usb_device *d, fe_bandwidth_t bw)
+static int af9005_fe_select_bw(struct dvb_usb_device *d, u32 bw)
 {
        u8 temp;
        switch (bw) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                temp = 0;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                temp = 1;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                temp = 2;
                break;
        default:
@@ -930,10 +930,11 @@ static int af9005_fe_init(struct dvb_frontend *fe)
 
        /* init other parameters: program cfoe and select bandwidth */
        deb_info("program cfoe\n");
-       if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ)))
+       ret = af9005_fe_program_cfoe(state->d, 6000000);
+       if (ret)
                return ret;
-       /* set read-update bit for constellation */
-       deb_info("set read-update bit for constellation\n");
+       /* set read-update bit for modulation */
+       deb_info("set read-update bit for modulation\n");
        if ((ret =
             af9005_write_register_bits(state->d, xd_p_reg_feq_read_update,
                                        reg_feq_read_update_pos,
@@ -943,8 +944,8 @@ static int af9005_fe_init(struct dvb_frontend *fe)
        /* sample code has a set MPEG TS code here
           but sniffing reveals that it doesn't do it */
 
-       /* set read-update bit to 1 for DCA constellation */
-       deb_info("set read-update bit 1 for DCA constellation\n");
+       /* set read-update bit to 1 for DCA modulation */
+       deb_info("set read-update bit 1 for DCA modulation\n");
        if ((ret =
             af9005_write_register_bits(state->d, xd_p_reg_dca_read_update,
                                        reg_dca_read_update_pos,
@@ -1099,15 +1100,15 @@ static int af9005_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
        return 0;
 }
 
-static int af9005_fe_set_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *fep)
+static int af9005_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct af9005_fe_state *state = fe->demodulator_priv;
        int ret;
        u8 temp, temp0, temp1, temp2;
 
        deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency,
-                fep->u.ofdm.bandwidth);
+                fep->bandwidth_hz);
        if (fe->ops.tuner_ops.release == NULL) {
                err("Tuner not attached");
                return -ENODEV;
@@ -1167,10 +1168,10 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
 
        /* select bandwidth */
        deb_info("select bandwidth");
-       ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth);
+       ret = af9005_fe_select_bw(state->d, fep->bandwidth_hz);
        if (ret)
                return ret;
-       ret = af9005_fe_program_cfoe(state->d, fep->u.ofdm.bandwidth);
+       ret = af9005_fe_program_cfoe(state->d, fep->bandwidth_hz);
        if (ret)
                return ret;
 
@@ -1189,7 +1190,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
                return ret;
        /* set tuner */
        deb_info("set tuner\n");
-       ret = fe->ops.tuner_ops.set_params(fe, fep);
+       ret = fe->ops.tuner_ops.set_params(fe);
        if (ret)
                return ret;
 
@@ -1225,9 +1226,9 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
        return 0;
 }
 
-static int af9005_fe_get_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *fep)
+static int af9005_fe_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct af9005_fe_state *state = fe->demodulator_priv;
        int ret;
        u8 temp;
@@ -1239,19 +1240,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
                                      &temp);
        if (ret)
                return ret;
-       deb_info("===== fe_get_frontend ==============\n");
+       deb_info("===== fe_get_frontend_legacy = =============\n");
        deb_info("CONSTELLATION ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.constellation = QPSK;
+               fep->modulation = QPSK;
                deb_info("QPSK\n");
                break;
        case 1:
-               fep->u.ofdm.constellation = QAM_16;
+               fep->modulation = QAM_16;
                deb_info("QAM_16\n");
                break;
        case 2:
-               fep->u.ofdm.constellation = QAM_64;
+               fep->modulation = QAM_64;
                deb_info("QAM_64\n");
                break;
        }
@@ -1266,19 +1267,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("HIERARCHY ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               fep->hierarchy = HIERARCHY_NONE;
                deb_info("NONE\n");
                break;
        case 1:
-               fep->u.ofdm.hierarchy_information = HIERARCHY_1;
+               fep->hierarchy = HIERARCHY_1;
                deb_info("1\n");
                break;
        case 2:
-               fep->u.ofdm.hierarchy_information = HIERARCHY_2;
+               fep->hierarchy = HIERARCHY_2;
                deb_info("2\n");
                break;
        case 3:
-               fep->u.ofdm.hierarchy_information = HIERARCHY_4;
+               fep->hierarchy = HIERARCHY_4;
                deb_info("4\n");
                break;
        }
@@ -1302,23 +1303,23 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("CODERATE HP ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.code_rate_HP = FEC_1_2;
+               fep->code_rate_HP = FEC_1_2;
                deb_info("FEC_1_2\n");
                break;
        case 1:
-               fep->u.ofdm.code_rate_HP = FEC_2_3;
+               fep->code_rate_HP = FEC_2_3;
                deb_info("FEC_2_3\n");
                break;
        case 2:
-               fep->u.ofdm.code_rate_HP = FEC_3_4;
+               fep->code_rate_HP = FEC_3_4;
                deb_info("FEC_3_4\n");
                break;
        case 3:
-               fep->u.ofdm.code_rate_HP = FEC_5_6;
+               fep->code_rate_HP = FEC_5_6;
                deb_info("FEC_5_6\n");
                break;
        case 4:
-               fep->u.ofdm.code_rate_HP = FEC_7_8;
+               fep->code_rate_HP = FEC_7_8;
                deb_info("FEC_7_8\n");
                break;
        }
@@ -1333,23 +1334,23 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("CODERATE LP ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.code_rate_LP = FEC_1_2;
+               fep->code_rate_LP = FEC_1_2;
                deb_info("FEC_1_2\n");
                break;
        case 1:
-               fep->u.ofdm.code_rate_LP = FEC_2_3;
+               fep->code_rate_LP = FEC_2_3;
                deb_info("FEC_2_3\n");
                break;
        case 2:
-               fep->u.ofdm.code_rate_LP = FEC_3_4;
+               fep->code_rate_LP = FEC_3_4;
                deb_info("FEC_3_4\n");
                break;
        case 3:
-               fep->u.ofdm.code_rate_LP = FEC_5_6;
+               fep->code_rate_LP = FEC_5_6;
                deb_info("FEC_5_6\n");
                break;
        case 4:
-               fep->u.ofdm.code_rate_LP = FEC_7_8;
+               fep->code_rate_LP = FEC_7_8;
                deb_info("FEC_7_8\n");
                break;
        }
@@ -1363,19 +1364,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("GUARD INTERVAL ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               fep->guard_interval = GUARD_INTERVAL_1_32;
                deb_info("1_32\n");
                break;
        case 1:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               fep->guard_interval = GUARD_INTERVAL_1_16;
                deb_info("1_16\n");
                break;
        case 2:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               fep->guard_interval = GUARD_INTERVAL_1_8;
                deb_info("1_8\n");
                break;
        case 3:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               fep->guard_interval = GUARD_INTERVAL_1_4;
                deb_info("1_4\n");
                break;
        }
@@ -1390,11 +1391,11 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("TRANSMISSION MODE ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               fep->transmission_mode = TRANSMISSION_MODE_2K;
                deb_info("2K\n");
                break;
        case 1:
-               fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               fep->transmission_mode = TRANSMISSION_MODE_8K;
                deb_info("8K\n");
                break;
        }
@@ -1406,15 +1407,15 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
        deb_info("BANDWIDTH ");
        switch (temp) {
        case 0:
-               fep->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+               fep->bandwidth_hz = 6000000;
                deb_info("6\n");
                break;
        case 1:
-               fep->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+               fep->bandwidth_hz = 7000000;
                deb_info("7\n");
                break;
        case 2:
-               fep->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+               fep->bandwidth_hz = 8000000;
                deb_info("8\n");
                break;
        }
@@ -1454,9 +1455,9 @@ struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_frontend_ops af9005_fe_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                 .name = "AF9005 USB DVB-T",
-                .type = FE_OFDM,
                 .frequency_min = 44250000,
                 .frequency_max = 867250000,
                 .frequency_stepsize = 250000,
index 4fc024d770406bf6588b1d409aa7be1df5ab98f0..af176b6ce738e78d4dc366ae0d56597f833f4e59 100644 (file)
@@ -977,11 +977,20 @@ static int af9005_usb_probe(struct usb_interface *intf,
                                   THIS_MODULE, NULL, adapter_nr);
 }
 
+enum af9005_usb_table_entry {
+       AFATECH_AF9005,
+       TERRATEC_AF9005,
+       ANSONIC_AF9005,
+};
+
 static struct usb_device_id af9005_usb_table[] = {
-       {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},
-       {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},
-       {USB_DEVICE(USB_VID_ANSONIC, USB_PID_ANSONIC_DVBT_USB)},
-       {0},
+       [AFATECH_AF9005] = {USB_DEVICE(USB_VID_AFATECH,
+                               USB_PID_AFATECH_AF9005)},
+       [TERRATEC_AF9005] = {USB_DEVICE(USB_VID_TERRATEC,
+                               USB_PID_TERRATEC_CINERGY_T_USB_XE)},
+       [ANSONIC_AF9005] = {USB_DEVICE(USB_VID_ANSONIC,
+                               USB_PID_ANSONIC_DVBT_USB)},
+       { }
 };
 
 MODULE_DEVICE_TABLE(usb, af9005_usb_table);
@@ -1041,15 +1050,15 @@ static struct dvb_usb_device_properties af9005_properties = {
        .num_device_descs = 3,
        .devices = {
                    {.name = "Afatech DVB-T USB1.1 stick",
-                    .cold_ids = {&af9005_usb_table[0], NULL},
+                    .cold_ids = {&af9005_usb_table[AFATECH_AF9005], NULL},
                     .warm_ids = {NULL},
                     },
                    {.name = "TerraTec Cinergy T USB XE",
-                    .cold_ids = {&af9005_usb_table[1], NULL},
+                    .cold_ids = {&af9005_usb_table[TERRATEC_AF9005], NULL},
                     .warm_ids = {NULL},
                     },
                    {.name = "Ansonic DVB-T USB1.1 stick",
-                    .cold_ids = {&af9005_usb_table[2], NULL},
+                    .cold_ids = {&af9005_usb_table[ANSONIC_AF9005], NULL},
                     .warm_ids = {NULL},
                     },
                    {NULL},
index 56cbd3636c318aa327e96bf8b1397131ac70d370..282a43d648df1817ec0d86ef4adf995706af52cf 100644 (file)
@@ -50,14 +50,14 @@ static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
 
 static struct af9013_config af9015_af9013_config[] = {
        {
-               .demod_address = AF9015_I2C_DEMOD,
-               .output_mode = AF9013_OUTPUT_MODE_USB,
+               .i2c_addr = AF9015_I2C_DEMOD,
+               .ts_mode = AF9013_TS_USB,
                .api_version = { 0, 1, 9, 0 },
                .gpio[0] = AF9013_GPIO_HI,
                .gpio[3] = AF9013_GPIO_TUNER_ON,
 
        }, {
-               .output_mode = AF9013_OUTPUT_MODE_SERIAL,
+               .ts_mode = AF9013_TS_SERIAL,
                .api_version = { 0, 1, 9, 0 },
                .gpio[0] = AF9013_GPIO_TUNER_ON,
                .gpio[1] = AF9013_GPIO_LO,
@@ -216,8 +216,8 @@ static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
 {
        struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
 
-       if (addr == af9015_af9013_config[0].demod_address ||
-           addr == af9015_af9013_config[1].demod_address)
+       if (addr == af9015_af9013_config[0].i2c_addr ||
+           addr == af9015_af9013_config[1].i2c_addr)
                req.addr_len = 3;
 
        return af9015_ctrl_msg(d, &req);
@@ -228,8 +228,8 @@ static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
 {
        struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
 
-       if (addr == af9015_af9013_config[0].demod_address ||
-           addr == af9015_af9013_config[1].demod_address)
+       if (addr == af9015_af9013_config[0].i2c_addr ||
+           addr == af9015_af9013_config[1].i2c_addr)
                req.addr_len = 3;
 
        return af9015_ctrl_msg(d, &req);
@@ -271,8 +271,8 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                return -EAGAIN;
 
        while (i < num) {
-               if (msg[i].addr == af9015_af9013_config[0].demod_address ||
-                   msg[i].addr == af9015_af9013_config[1].demod_address) {
+               if (msg[i].addr == af9015_af9013_config[0].i2c_addr ||
+                   msg[i].addr == af9015_af9013_config[1].i2c_addr) {
                        addr = msg[i].buf[0] << 8;
                        addr += msg[i].buf[1];
                        mbox = msg[i].buf[2];
@@ -288,8 +288,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                                ret = -EOPNOTSUPP;
                                goto error;
                        }
-                       if (msg[i].addr ==
-                               af9015_af9013_config[0].demod_address)
+                       if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
                                req.cmd = READ_MEMORY;
                        else
                                req.cmd = READ_I2C;
@@ -307,7 +306,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                                goto error;
                        }
                        if (msg[i].addr ==
-                               af9015_af9013_config[0].demod_address) {
+                               af9015_af9013_config[0].i2c_addr) {
                                ret = -EINVAL;
                                goto error;
                        }
@@ -325,8 +324,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
                                ret = -EOPNOTSUPP;
                                goto error;
                        }
-                       if (msg[i].addr ==
-                               af9015_af9013_config[0].demod_address)
+                       if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
                                req.cmd = WRITE_MEMORY;
                        else
                                req.cmd = WRITE_I2C;
@@ -508,7 +506,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
        msleep(100);
 
        ret = af9015_read_reg_i2c(d,
-               af9015_af9013_config[1].demod_address, 0x98be, &val);
+               af9015_af9013_config[1].i2c_addr, 0x98be, &val);
        if (ret)
                goto error;
        else
@@ -536,7 +534,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
                goto error;
 
        /* request boot firmware */
-       ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address,
+       ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].i2c_addr,
                0xe205, 1);
        deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
        if (ret)
@@ -547,7 +545,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
 
                /* check firmware status */
                ret = af9015_read_reg_i2c(d,
-                       af9015_af9013_config[1].demod_address, 0x98be, &val);
+                       af9015_af9013_config[1].i2c_addr, 0x98be, &val);
                deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
                        __func__, ret, val);
                if (ret)
@@ -840,7 +838,7 @@ static int af9015_read_config(struct usb_device *udev)
        if (ret)
                goto error;
 
-       deb_info("%s: IR mode:%d\n", __func__, val);
+       deb_info("%s: IR mode=%d\n", __func__, val);
        for (i = 0; i < af9015_properties_count; i++) {
                if (val == AF9015_IR_MODE_DISABLED)
                        af9015_properties[i].rc.core.rc_codes = NULL;
@@ -854,7 +852,7 @@ static int af9015_read_config(struct usb_device *udev)
        if (ret)
                goto error;
        af9015_config.dual_mode = val;
-       deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
+       deb_info("%s: TS mode=%d\n", __func__, af9015_config.dual_mode);
 
        /* Set adapter0 buffer size according to USB port speed, adapter1 buffer
           size can be static because it is enabled only USB2.0 */
@@ -878,7 +876,7 @@ static int af9015_read_config(struct usb_device *udev)
                ret = af9015_rw_udev(udev, &req);
                if (ret)
                        goto error;
-               af9015_af9013_config[1].demod_address = val;
+               af9015_af9013_config[1].i2c_addr = val;
 
                /* enable 2nd adapter */
                for (i = 0; i < af9015_properties_count; i++)
@@ -900,34 +898,38 @@ static int af9015_read_config(struct usb_device *udev)
                        goto error;
                switch (val) {
                case 0:
-                       af9015_af9013_config[i].adc_clock = 28800;
+                       af9015_af9013_config[i].clock = 28800000;
                        break;
                case 1:
-                       af9015_af9013_config[i].adc_clock = 20480;
+                       af9015_af9013_config[i].clock = 20480000;
                        break;
                case 2:
-                       af9015_af9013_config[i].adc_clock = 28000;
+                       af9015_af9013_config[i].clock = 28000000;
                        break;
                case 3:
-                       af9015_af9013_config[i].adc_clock = 25000;
+                       af9015_af9013_config[i].clock = 25000000;
                        break;
                };
-               deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i,
-                       val, af9015_af9013_config[i].adc_clock);
+               deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i,
+                       val, af9015_af9013_config[i].clock);
 
-               /* tuner IF */
+               /* IF frequency */
                req.addr = AF9015_EEPROM_IF1H + offset;
                ret = af9015_rw_udev(udev, &req);
                if (ret)
                        goto error;
-               af9015_af9013_config[i].tuner_if = val << 8;
+
+               af9015_af9013_config[i].if_frequency = val << 8;
+
                req.addr = AF9015_EEPROM_IF1L + offset;
                ret = af9015_rw_udev(udev, &req);
                if (ret)
                        goto error;
-               af9015_af9013_config[i].tuner_if += val;
-               deb_info("%s: [%d] IF1:%d\n", __func__, i,
-                       af9015_af9013_config[0].tuner_if);
+
+               af9015_af9013_config[i].if_frequency += val;
+               af9015_af9013_config[i].if_frequency *= 1000;
+               deb_info("%s: [%d] IF frequency=%d\n", __func__, i,
+                       af9015_af9013_config[0].if_frequency);
 
                /* MT2060 IF1 */
                req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
@@ -940,7 +942,7 @@ static int af9015_read_config(struct usb_device *udev)
                if (ret)
                        goto error;
                af9015_config.mt2060_if1[i] += val;
-               deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i,
+               deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i,
                        af9015_config.mt2060_if1[i]);
 
                /* tuner */
@@ -957,30 +959,30 @@ static int af9015_read_config(struct usb_device *udev)
                case AF9013_TUNER_TDA18271:
                case AF9013_TUNER_QT1010A:
                case AF9013_TUNER_TDA18218:
-                       af9015_af9013_config[i].rf_spec_inv = 1;
+                       af9015_af9013_config[i].spec_inv = 1;
                        break;
                case AF9013_TUNER_MXL5003D:
                case AF9013_TUNER_MXL5005D:
                case AF9013_TUNER_MXL5005R:
                case AF9013_TUNER_MXL5007T:
-                       af9015_af9013_config[i].rf_spec_inv = 0;
+                       af9015_af9013_config[i].spec_inv = 0;
                        break;
                case AF9013_TUNER_MC44S803:
                        af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
-                       af9015_af9013_config[i].rf_spec_inv = 1;
+                       af9015_af9013_config[i].spec_inv = 1;
                        break;
                default:
-                       warn("tuner id:%d not supported, please report!", val);
+                       warn("tuner id=%d not supported, please report!", val);
                        return -ENODEV;
                };
 
                af9015_af9013_config[i].tuner = val;
-               deb_info("%s: [%d] tuner id:%d\n", __func__, i, val);
+               deb_info("%s: [%d] tuner id=%d\n", __func__, i, val);
        }
 
 error:
        if (ret)
-               err("eeprom read failed:%d", ret);
+               err("eeprom read failed=%d", ret);
 
        /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
           content :-( Override some wrong values here. Ditto for the
@@ -998,7 +1000,7 @@ error:
                        af9015_properties[i].num_adapters = 1;
 
                /* set correct IF */
-               af9015_af9013_config[0].tuner_if = 4570;
+               af9015_af9013_config[0].if_frequency = 4570000;
        }
 
        return ret;
@@ -1093,9 +1095,79 @@ error:
        return ret;
 }
 
+/* override demod callbacks for resource locking */
+static int af9015_af9013_set_frontend(struct dvb_frontend *fe)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct af9015_state *priv = adap->dev->priv;
+
+       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
+               return -EAGAIN;
+
+       ret = priv->set_frontend[adap->id](fe);
+
+       mutex_unlock(&adap->dev->usb_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_read_status(struct dvb_frontend *fe,
+       fe_status_t *status)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct af9015_state *priv = adap->dev->priv;
+
+       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
+               return -EAGAIN;
+
+       ret = priv->read_status[adap->id](fe, status);
+
+       mutex_unlock(&adap->dev->usb_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_init(struct dvb_frontend *fe)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct af9015_state *priv = adap->dev->priv;
+
+       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
+               return -EAGAIN;
+
+       ret = priv->init[adap->id](fe);
+
+       mutex_unlock(&adap->dev->usb_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_sleep(struct dvb_frontend *fe)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct af9015_state *priv = adap->dev->priv;
+
+       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
+               return -EAGAIN;
+
+       ret = priv->sleep[adap->id](fe);
+
+       mutex_unlock(&adap->dev->usb_mutex);
+
+       return ret;
+}
+
 static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
+       struct af9015_state *state = adap->dev->priv;
 
        if (adap->id == 1) {
                /* copy firmware to 2nd demodulator */
@@ -1116,6 +1188,32 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
        adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
                &adap->dev->i2c_adap);
 
+       /*
+        * AF9015 firmware does not like if it gets interrupted by I2C adapter
+        * request on some critical phases. During normal operation I2C adapter
+        * is used only 2nd demodulator and tuner on dual tuner devices.
+        * Override demodulator callbacks and use mutex for limit access to
+        * those "critical" paths to keep AF9015 happy.
+        * Note: we abuse unused usb_mutex here.
+        */
+       if (adap->fe_adap[0].fe) {
+               state->set_frontend[adap->id] =
+                       adap->fe_adap[0].fe->ops.set_frontend;
+               adap->fe_adap[0].fe->ops.set_frontend =
+                       af9015_af9013_set_frontend;
+
+               state->read_status[adap->id] =
+                       adap->fe_adap[0].fe->ops.read_status;
+               adap->fe_adap[0].fe->ops.read_status =
+                       af9015_af9013_read_status;
+
+               state->init[adap->id] = adap->fe_adap[0].fe->ops.init;
+               adap->fe_adap[0].fe->ops.init = af9015_af9013_init;
+
+               state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep;
+               adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep;
+       }
+
        return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
@@ -1245,49 +1343,112 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
        return ret;
 }
 
+enum af9015_usb_table_entry {
+       AFATECH_9015,
+       AFATECH_9016,
+       WINFAST_DTV_GOLD,
+       PINNACLE_PCTV_71E,
+       KWORLD_PLUSTV_399U,
+       TINYTWIN,
+       AZUREWAVE_TU700,
+       TERRATEC_AF9015,
+       KWORLD_PLUSTV_PC160,
+       AVERTV_VOLAR_X,
+       XTENSIONS_380U,
+       MSI_DIGIVOX_DUO,
+       AVERTV_VOLAR_X_REV2,
+       TELESTAR_STARSTICK_2,
+       AVERMEDIA_A309_USB,
+       MSI_DIGIVOX_MINI_III,
+       KWORLD_E396,
+       KWORLD_E39B,
+       KWORLD_E395,
+       TREKSTOR_DVBT,
+       AVERTV_A850,
+       AVERTV_A805,
+       CONCEPTRONIC_CTVDIGRCU,
+       KWORLD_MC810,
+       GENIUS_TVGO_DVB_T03,
+       KWORLD_399U_2,
+       KWORLD_PC160_T,
+       SVEON_STV20,
+       TINYTWIN_2,
+       WINFAST_DTV2000DS,
+       KWORLD_UB383_T,
+       KWORLD_E39A,
+       AVERMEDIA_A815M,
+       CINERGY_T_STICK_RC,
+       CINERGY_T_DUAL_RC,
+       AVERTV_A850T,
+       TINYTWIN_3,
+       SVEON_STV22,
+};
+
 static struct usb_device_id af9015_usb_table[] = {
-/*  0 */{USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9015_9015)},
-       {USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9015_9016)},
-       {USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_GOLD)},
-       {USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV71E)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_399U)},
-/*  5 */{USB_DEVICE(USB_VID_VISIONPLUS,
-               USB_PID_TINYTWIN)},
-       {USB_DEVICE(USB_VID_VISIONPLUS,
-               USB_PID_AZUREWAVE_AD_TU700)},
-       {USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_PC160_2T)},
-       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
-/* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
-       {USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGIVOX_DUO)},
-       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
-       {USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
-       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
-/* 15 */{USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGI_VOX_MINI_III)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_2)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_3)},
-       {USB_DEVICE(USB_VID_AFATECH,   USB_PID_TREKSTOR_DVBT)},
-/* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
-       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_CONCEPTRONIC_CTVDIGRCU)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_MC810)},
-       {USB_DEVICE(USB_VID_KYE,       USB_PID_GENIUS_TVGO_DVB_T03)},
-/* 25 */{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_399U_2)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_PC160_T)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_SVEON_STV20)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_TINYTWIN_2)},
-       {USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV2000DS)},
-/* 30 */{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_UB383_T)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_4)},
-       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
-       {USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
-       {USB_DEVICE(USB_VID_TERRATEC,
-               USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
-/* 35 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
-       {USB_DEVICE(USB_VID_GTEK,      USB_PID_TINYTWIN_3)},
-       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_SVEON_STV22)},
-       {0},
+       [AFATECH_9015] =
+               {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
+       [AFATECH_9016] =
+               {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
+       [WINFAST_DTV_GOLD] =
+               {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
+       [PINNACLE_PCTV_71E] =
+               {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
+       [KWORLD_PLUSTV_399U] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
+       [TINYTWIN] = {USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)},
+       [AZUREWAVE_TU700] =
+               {USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)},
+       [TERRATEC_AF9015] = {USB_DEVICE(USB_VID_TERRATEC,
+                               USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
+       [KWORLD_PLUSTV_PC160] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
+       [AVERTV_VOLAR_X] =
+               {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
+       [XTENSIONS_380U] =
+               {USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
+       [MSI_DIGIVOX_DUO] =
+               {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
+       [AVERTV_VOLAR_X_REV2] =
+               {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
+       [TELESTAR_STARSTICK_2] =
+               {USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
+       [AVERMEDIA_A309_USB] =
+               {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
+       [MSI_DIGIVOX_MINI_III] =
+               {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
+       [KWORLD_E396] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
+       [KWORLD_E39B] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
+       [KWORLD_E395] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
+       [TREKSTOR_DVBT] = {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
+       [AVERTV_A850] = {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+       [AVERTV_A805] = {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
+       [CONCEPTRONIC_CTVDIGRCU] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
+       [KWORLD_MC810] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
+       [GENIUS_TVGO_DVB_T03] =
+               {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
+       [KWORLD_399U_2] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
+       [KWORLD_PC160_T] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
+       [SVEON_STV20] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
+       [TINYTWIN_2] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
+       [WINFAST_DTV2000DS] =
+               {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
+       [KWORLD_UB383_T] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
+       [KWORLD_E39A] =
+               {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
+       [AVERMEDIA_A815M] =
+               {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
+       [CINERGY_T_STICK_RC] = {USB_DEVICE(USB_VID_TERRATEC,
+                               USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
+       [CINERGY_T_DUAL_RC] = {USB_DEVICE(USB_VID_TERRATEC,
+                               USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
+       [AVERTV_A850T] =
+               {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
+       [TINYTWIN_3] = {USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
+       [SVEON_STV22] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
+       { }
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
 
@@ -1362,68 +1523,104 @@ static struct dvb_usb_device_properties af9015_properties[] = {
                .devices = {
                        {
                                .name = "Afatech AF9015 DVB-T USB2.0 stick",
-                               .cold_ids = {&af9015_usb_table[0],
-                                            &af9015_usb_table[1], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AFATECH_9015],
+                                       &af9015_usb_table[AFATECH_9016],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Leadtek WinFast DTV Dongle Gold",
-                               .cold_ids = {&af9015_usb_table[2], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[WINFAST_DTV_GOLD],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Pinnacle PCTV 71e",
-                               .cold_ids = {&af9015_usb_table[3], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[PINNACLE_PCTV_71E],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld PlusTV Dual DVB-T Stick " \
                                        "(DVB-T 399U)",
-                               .cold_ids = {&af9015_usb_table[4],
-                                            &af9015_usb_table[25], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_PLUSTV_399U],
+                                       &af9015_usb_table[KWORLD_399U_2],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "DigitalNow TinyTwin DVB-T Receiver",
-                               .cold_ids = {&af9015_usb_table[5],
-                                            &af9015_usb_table[28],
-                                            &af9015_usb_table[36], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[TINYTWIN],
+                                       &af9015_usb_table[TINYTWIN_2],
+                                       &af9015_usb_table[TINYTWIN_3],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "TwinHan AzureWave AD-TU700(704J)",
-                               .cold_ids = {&af9015_usb_table[6], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AZUREWAVE_TU700],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "TerraTec Cinergy T USB XE",
-                               .cold_ids = {&af9015_usb_table[7], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[TERRATEC_AF9015],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld PlusTV Dual DVB-T PCI " \
                                        "(DVB-T PC160-2T)",
-                               .cold_ids = {&af9015_usb_table[8], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_PLUSTV_PC160],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "AVerMedia AVerTV DVB-T Volar X",
-                               .cold_ids = {&af9015_usb_table[9], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERTV_VOLAR_X],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "TerraTec Cinergy T Stick RC",
-                               .cold_ids = {&af9015_usb_table[33], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[CINERGY_T_STICK_RC],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "TerraTec Cinergy T Stick Dual RC",
-                               .cold_ids = {&af9015_usb_table[34], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[CINERGY_T_DUAL_RC],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "AverMedia AVerTV Red HD+ (A850T)",
-                               .cold_ids = {&af9015_usb_table[35], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERTV_A850T],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                }
@@ -1496,57 +1693,87 @@ static struct dvb_usb_device_properties af9015_properties[] = {
                .devices = {
                        {
                                .name = "Xtensions XD-380",
-                               .cold_ids = {&af9015_usb_table[10], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[XTENSIONS_380U],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "MSI DIGIVOX Duo",
-                               .cold_ids = {&af9015_usb_table[11], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[MSI_DIGIVOX_DUO],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
-                               .cold_ids = {&af9015_usb_table[12], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERTV_VOLAR_X_REV2],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Telestar Starstick 2",
-                               .cold_ids = {&af9015_usb_table[13], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[TELESTAR_STARSTICK_2],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "AVerMedia A309",
-                               .cold_ids = {&af9015_usb_table[14], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERMEDIA_A309_USB],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "MSI Digi VOX mini III",
-                               .cold_ids = {&af9015_usb_table[15], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[MSI_DIGIVOX_MINI_III],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld USB DVB-T TV Stick II " \
                                        "(VS-DVB-T 395U)",
-                               .cold_ids = {&af9015_usb_table[16],
-                                            &af9015_usb_table[17],
-                                            &af9015_usb_table[18],
-                                            &af9015_usb_table[31], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_E396],
+                                       &af9015_usb_table[KWORLD_E39B],
+                                       &af9015_usb_table[KWORLD_E395],
+                                       &af9015_usb_table[KWORLD_E39A],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "TrekStor DVB-T USB Stick",
-                               .cold_ids = {&af9015_usb_table[19], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[TREKSTOR_DVBT],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "AverMedia AVerTV Volar Black HD " \
                                        "(A850)",
-                               .cold_ids = {&af9015_usb_table[20], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERTV_A850],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
-                               .cold_ids = {&af9015_usb_table[37], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[SVEON_STV22],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                }
@@ -1619,50 +1846,77 @@ static struct dvb_usb_device_properties af9015_properties[] = {
                .devices = {
                        {
                                .name = "AverMedia AVerTV Volar GPS 805 (A805)",
-                               .cold_ids = {&af9015_usb_table[21], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERTV_A805],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
                                        "V3.0",
-                               .cold_ids = {&af9015_usb_table[22], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[CONCEPTRONIC_CTVDIGRCU],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld Digial MC-810",
-                               .cold_ids = {&af9015_usb_table[23], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_MC810],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Genius TVGo DVB-T03",
-                               .cold_ids = {&af9015_usb_table[24], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[GENIUS_TVGO_DVB_T03],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld PlusTV DVB-T PCI Pro Card " \
                                        "(DVB-T PC160-T)",
-                               .cold_ids = {&af9015_usb_table[26], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_PC160_T],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Sveon STV20 Tuner USB DVB-T HDTV",
-                               .cold_ids = {&af9015_usb_table[27], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[SVEON_STV20],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "Leadtek WinFast DTV2000DS",
-                               .cold_ids = {&af9015_usb_table[29], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[WINFAST_DTV2000DS],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "KWorld USB DVB-T Stick Mobile " \
                                        "(UB383-T)",
-                               .cold_ids = {&af9015_usb_table[30], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[KWORLD_UB383_T],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                        {
                                .name = "AverMedia AVerTV Volar M (A815Mac)",
-                               .cold_ids = {&af9015_usb_table[32], NULL},
+                               .cold_ids = {
+                                       &af9015_usb_table[AVERMEDIA_A815M],
+                                       NULL
+                               },
                                .warm_ids = {NULL},
                        },
                }
index 6252ea6c19042b75a92e6aee88b3d9ec258f24da..f619063fa72f6a03f663da283ce91d1e7d3b6623 100644 (file)
@@ -102,6 +102,12 @@ struct af9015_state {
        u8 rc_repeat;
        u32 rc_keycode;
        u8 rc_last[4];
+
+       /* for demod callback override */
+       int (*set_frontend[2]) (struct dvb_frontend *fe);
+       int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status);
+       int (*init[2]) (struct dvb_frontend *fe);
+       int (*sleep[2]) (struct dvb_frontend *fe);
 };
 
 struct af9015_config {
index b39f14f85e7163fb8fa7948c4c6c1c9b8e4e2770..d66192974d68a0a2de44fd41f156f7b6c9c90a85 100644 (file)
@@ -41,6 +41,7 @@
 #include "stv0900.h"
 #include "stv6110.h"
 #include "isl6423.h"
+#include "cxd2820r.h"
 
 /* debug */
 static int dvb_usb_anysee_debug;
@@ -66,10 +67,12 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
                return -EAGAIN;
 
+       deb_xfer(">>> ");
+       debug_dump(buf, slen, deb_xfer);
+
        /* We need receive one message more after dvb_usb_generic_rw due
           to weird transaction flow, which is 1 x send + 2 x receive. */
        ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
-
        if (!ret) {
                /* receive 2nd answer */
                ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
@@ -79,7 +82,10 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
                        err("%s: recv bulk message failed: %d", __func__, ret);
                else {
                        deb_xfer("<<< ");
-                       debug_dump(buf, act_len, deb_xfer);
+                       debug_dump(buf, rlen, deb_xfer);
+
+                       if (buf[63] != 0x4f)
+                               deb_info("%s: cmd failed\n", __func__);
                }
        }
 
@@ -129,6 +135,29 @@ static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
        return anysee_write_reg(d, reg, val);
 }
 
+/* read single register with mask */
+static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val,
+       u8 mask)
+{
+       int ret, i;
+       u8 tmp;
+
+       ret = anysee_read_reg(d, reg, &tmp);
+       if (ret)
+               return ret;
+
+       tmp &= mask;
+
+       /* find position of the first bit */
+       for (i = 0; i < 8; i++) {
+               if ((mask >> i) & 0x01)
+                       break;
+       }
+       *val = tmp >> i;
+
+       return 0;
+}
+
 static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
 {
        u8 buf[] = {CMD_GET_HW_INFO};
@@ -156,22 +185,6 @@ static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
        return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
-static int anysee_init(struct dvb_usb_device *d)
-{
-       int ret;
-       /* LED light */
-       ret = anysee_led_ctrl(d, 0x01, 0x03);
-       if (ret)
-               return ret;
-
-       /* enable IR */
-       ret = anysee_ir_ctrl(d, 1);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
 /* I2C */
 static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
        int num)
@@ -297,7 +310,7 @@ static struct tda10023_config anysee_tda10023_tda18212_config = {
        .pll_m  = 12,
        .pll_p  = 3,
        .pll_n  = 1,
-       .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+       .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B,
        .deltaf = 0xba02,
 };
 
@@ -309,6 +322,17 @@ static struct tda18212_config anysee_tda18212_config = {
        .if_dvbc = 5000,
 };
 
+static struct tda18212_config anysee_tda18212_config2 = {
+       .i2c_address = 0x60 /* (0xc0 >> 1) */,
+       .if_dvbt_6 = 3550,
+       .if_dvbt_7 = 3700,
+       .if_dvbt_8 = 4150,
+       .if_dvbt2_6 = 3250,
+       .if_dvbt2_7 = 4000,
+       .if_dvbt2_8 = 4000,
+       .if_dvbc = 5000,
+};
+
 static struct cx24116_config anysee_cx24116_config = {
        .demod_address = (0xaa >> 1),
        .mpg_clk_pos_pol = 0x00,
@@ -339,6 +363,11 @@ static struct isl6423_config anysee_isl6423_config = {
        .addr = (0x10 >> 1),
 };
 
+static struct cxd2820r_config anysee_cxd2820r_config = {
+       .i2c_address = 0x6d, /* (0xda >> 1) */
+       .ts_mode = 0x38,
+};
+
 /*
  * New USB device strings: Mfr=1, Product=2, SerialNumber=0
  * Manufacturer: AMT.CO.KR
@@ -421,6 +450,14 @@ static struct isl6423_config anysee_isl6423_config = {
  * IOA[7] TS 1=enabled
  * IOE[5] STV0903 1=enabled
  *
+ * E7 T2C VID=1c73 PID=861f HW=20 FW=0.1 AMTCI=0.5 "anysee-E7T2C(LP)"
+ * PCB: 508T2C (rev0.3)
+ * parts: DNOQ44QCH106A(CXD2820R, TDA18212), TDA8024
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] CXD2820R 1=enabled
+ *
  * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)"
  * PCB: 508PTC (rev0.5)
  * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
@@ -437,7 +474,7 @@ static struct isl6423_config anysee_isl6423_config = {
  * IOD[6] ZL10353 1=enabled
  * IOE[0] IF 0=enabled
  *
- * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
+ * E7 PS2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
  * PCB: 508PS2 (rev0.4)
  * parts: DNBU10512IST(STV0903, STV6110), ISL6423
  * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
@@ -446,6 +483,16 @@ static struct isl6423_config anysee_isl6423_config = {
  * IOE[5] STV0903 1=enabled
  */
 
+
+/* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */
+static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+       /* enable / disable tuner access on IOE[4] */
+       return anysee_wr_reg_mask(adap->dev, REG_IOE, (enable << 4), 0x10);
+}
+
 static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
 {
        struct dvb_usb_adapter *adap = fe->dvb->priv;
@@ -577,7 +624,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
        /* detect hardware only once */
        if (adap->fe_adap[0].fe == NULL) {
                /* Check which hardware we have.
-                * We must do this call two times to get reliable values (hw bug).
+                * We must do this call two times to get reliable values
+                * (hw/fw bug).
                 */
                ret = anysee_get_hw_info(adap->dev, hw_info);
                if (ret)
@@ -606,14 +654,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                        break;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
-                       &adap->dev->i2c_adap);
+               adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+                       &anysee_mt352_config, &adap->dev->i2c_adap);
                if (adap->fe_adap[0].fe)
                        break;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-                       &adap->dev->i2c_adap);
+               adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+                       &anysee_zl10353_config, &adap->dev->i2c_adap);
 
                break;
        case ANYSEE_HW_507CD: /* 6 */
@@ -665,8 +713,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
-                       &adap->dev->i2c_adap);
+               adap->fe_adap[0].fe = dvb_attach(cx24116_attach,
+                       &anysee_cx24116_config, &adap->dev->i2c_adap);
 
                break;
        case ANYSEE_HW_507FA: /* 15 */
@@ -747,17 +795,19 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                        }
                }
 
+               /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+               if (tmp == 0xc7) {
+                       if (adap->fe_adap[state->fe_id].fe)
+                               adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
+                                       anysee_i2c_gate_ctrl;
+               }
+
                break;
        case ANYSEE_HW_508TC: /* 18 */
        case ANYSEE_HW_508PTC: /* 21 */
                /* E7 TC */
                /* E7 PTC */
 
-               /* enable transport stream on IOA[7] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
-               if (ret)
-                       goto error;
-
                if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
                        /* disable DVB-T demod on IOD[6] */
                        ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
@@ -772,7 +822,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                                goto error;
 
                        /* attach demod */
-                       adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+                       adap->fe_adap[state->fe_id].fe =
+                               dvb_attach(tda10023_attach,
                                &anysee_tda10023_tda18212_config,
                                &adap->dev->i2c_adap, 0x48);
                } else {
@@ -789,11 +840,19 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                                goto error;
 
                        /* attach demod */
-                       adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+                       adap->fe_adap[state->fe_id].fe =
+                               dvb_attach(zl10353_attach,
                                &anysee_zl10353_tda18212_config,
                                &adap->dev->i2c_adap);
                }
 
+               /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+               if (adap->fe_adap[state->fe_id].fe)
+                       adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
+                               anysee_i2c_gate_ctrl;
+
+               state->has_ci = true;
+
                break;
        case ANYSEE_HW_508S2: /* 19 */
        case ANYSEE_HW_508PS2: /* 22 */
@@ -803,19 +862,41 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                if (state->fe_id)
                        break;
 
-               /* enable transport stream on IOA[7] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+               /* enable DVB-S/S2 demod on IOE[5] */
+               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
-               /* enable DVB-S/S2 demod on IOE[5] */
+               /* attach demod */
+               adap->fe_adap[0].fe = dvb_attach(stv0900_attach,
+                       &anysee_stv0900_config, &adap->dev->i2c_adap, 0);
+
+               state->has_ci = true;
+
+               break;
+       case ANYSEE_HW_508T2C: /* 20 */
+               /* E7 T2C */
+
+               /* enable DVB-T/T2/C demod on IOE[5] */
                ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
-               /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
-                       &adap->dev->i2c_adap, 0);
+               if (state->fe_id == 0)  {
+                       /* DVB-T/T2 */
+                       adap->fe_adap[state->fe_id].fe =
+                               dvb_attach(cxd2820r_attach,
+                               &anysee_cxd2820r_config,
+                               &adap->dev->i2c_adap, NULL);
+               } else {
+                       /* DVB-C */
+                       adap->fe_adap[state->fe_id].fe =
+                               dvb_attach(cxd2820r_attach,
+                               &anysee_cxd2820r_config,
+                               &adap->dev->i2c_adap, adap->fe_adap[0].fe);
+               }
+
+               state->has_ci = true;
 
                break;
        }
@@ -842,24 +923,26 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* E30 */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
-                       NULL, DVB_PLL_THOMSON_DTT7579);
+               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
+                       (0xc2 >> 1), NULL, DVB_PLL_THOMSON_DTT7579);
 
                break;
        case ANYSEE_HW_507CD: /* 6 */
                /* E30 Plus */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
-                       &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
+               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
+                       (0xc2 >> 1), &adap->dev->i2c_adap,
+                       DVB_PLL_THOMSON_DTT7579);
 
                break;
        case ANYSEE_HW_507DC: /* 10 */
                /* E30 C Plus */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
-                       &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
+                       (0xc0 >> 1), &adap->dev->i2c_adap,
+                       DVB_PLL_SAMSUNG_DTOS403IH102A);
 
                break;
        case ANYSEE_HW_507SI: /* 11 */
@@ -877,22 +960,12 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* Try first attach TDA18212 silicon tuner on IOE[4], if that
                 * fails attach old simple PLL. */
 
-               /* enable tuner on IOE[4] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
-               if (ret)
-                       goto error;
-
                /* attach tuner */
                fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
                        &adap->dev->i2c_adap, &anysee_tda18212_config);
                if (fe)
                        break;
 
-               /* disable tuner on IOE[4] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
-               if (ret)
-                       goto error;
-
                /* attach tuner */
                fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
                        (0xc0 >> 1), &adap->dev->i2c_adap,
@@ -904,11 +977,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* E7 TC */
                /* E7 PTC */
 
-               /* enable tuner on IOE[4] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
-               if (ret)
-                       goto error;
-
                /* attach tuner */
                fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
                        &adap->dev->i2c_adap, &anysee_tda18212_config);
@@ -930,6 +998,15 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                }
 
                break;
+
+       case ANYSEE_HW_508T2C: /* 20 */
+               /* E7 T2C */
+
+               /* attach tuner */
+               fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+                       &adap->dev->i2c_adap, &anysee_tda18212_config2);
+
+               break;
        default:
                fe = NULL;
        }
@@ -939,7 +1016,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
        else
                ret = -ENODEV;
 
-error:
        return ret;
 }
 
@@ -969,6 +1045,201 @@ static int anysee_rc_query(struct dvb_usb_device *d)
        return 0;
 }
 
+static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
+       int addr)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+       u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1};
+       u8 val;
+
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
+       if (ret)
+               return ret;
+
+       return val;
+}
+
+static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
+       int addr, u8 val)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+       u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val};
+
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot,
+       u8 addr)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+       u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1};
+       u8 val;
+
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
+       if (ret)
+               return ret;
+
+       return val;
+}
+
+static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot,
+       u8 addr, u8 val)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+       u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val};
+
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+       struct anysee_state *state = d->priv;
+
+       state->ci_cam_ready = jiffies + msecs_to_jiffies(1000);
+
+       ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
+       if (ret)
+               return ret;
+
+       msleep(300);
+
+       ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+
+       ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
+       if (ret)
+               return ret;
+
+       msleep(30);
+
+       ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
+{
+       struct dvb_usb_device *d = ci->data;
+       int ret;
+
+       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
+       int open)
+{
+       struct dvb_usb_device *d = ci->data;
+       struct anysee_state *state = d->priv;
+       int ret;
+       u8 tmp;
+
+       ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40);
+       if (ret)
+               return ret;
+
+       if (tmp == 0) {
+               ret = DVB_CA_EN50221_POLL_CAM_PRESENT;
+               if (time_after(jiffies, state->ci_cam_ready))
+                       ret |= DVB_CA_EN50221_POLL_CAM_READY;
+       }
+
+       return ret;
+}
+
+static int anysee_ci_init(struct dvb_usb_device *d)
+{
+       struct anysee_state *state = d->priv;
+       int ret;
+
+       state->ci.owner               = THIS_MODULE;
+       state->ci.read_attribute_mem  = anysee_ci_read_attribute_mem;
+       state->ci.write_attribute_mem = anysee_ci_write_attribute_mem;
+       state->ci.read_cam_control    = anysee_ci_read_cam_control;
+       state->ci.write_cam_control   = anysee_ci_write_cam_control;
+       state->ci.slot_reset          = anysee_ci_slot_reset;
+       state->ci.slot_shutdown       = anysee_ci_slot_shutdown;
+       state->ci.slot_ts_enable      = anysee_ci_slot_ts_enable;
+       state->ci.poll_slot_status    = anysee_ci_poll_slot_status;
+       state->ci.data                = d;
+
+       ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+       if (ret)
+               return ret;
+
+       ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void anysee_ci_release(struct dvb_usb_device *d)
+{
+       struct anysee_state *state = d->priv;
+
+       /* detach CI */
+       if (state->has_ci)
+               dvb_ca_en50221_release(&state->ci);
+
+       return;
+}
+
+static int anysee_init(struct dvb_usb_device *d)
+{
+       struct anysee_state *state = d->priv;
+       int ret;
+
+       /* LED light */
+       ret = anysee_led_ctrl(d, 0x01, 0x03);
+       if (ret)
+               return ret;
+
+       /* enable IR */
+       ret = anysee_ir_ctrl(d, 1);
+       if (ret)
+               return ret;
+
+       /* attach CI */
+       if (state->has_ci) {
+               ret = anysee_ci_init(d);
+               if (ret) {
+                       state->has_ci = false;
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /* DVB USB Driver stuff */
 static struct dvb_usb_device_properties anysee_properties;
 
@@ -1010,6 +1281,16 @@ static int anysee_probe(struct usb_interface *intf,
        return anysee_init(d);
 }
 
+static void anysee_disconnect(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+       anysee_ci_release(d);
+       dvb_usb_device_exit(intf);
+
+       return;
+}
+
 static struct usb_device_id anysee_table[] = {
        { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
        { USB_DEVICE(USB_VID_AMT,     USB_PID_ANYSEE) },
@@ -1029,7 +1310,7 @@ static struct dvb_usb_device_properties anysee_properties = {
                {
                .num_frontends    = 2,
                .frontend_ctrl    = anysee_frontend_ctrl,
-               .fe = {{
+               .fe = { {
                        .streaming_ctrl   = anysee_streaming_ctrl,
                        .frontend_attach  = anysee_frontend_attach,
                        .tuner_attach     = anysee_tuner_attach,
@@ -1057,7 +1338,7 @@ static struct dvb_usb_device_properties anysee_properties = {
                                        }
                                }
                        },
-               }},
+               } },
                }
        },
 
@@ -1087,7 +1368,7 @@ static struct dvb_usb_device_properties anysee_properties = {
 static struct usb_driver anysee_driver = {
        .name       = "dvb_usb_anysee",
        .probe      = anysee_probe,
-       .disconnect = dvb_usb_device_exit,
+       .disconnect = anysee_disconnect,
        .id_table   = anysee_table,
 };
 
index 57ee500b8c0e1c16d8c41e8bf51d40b1e6058014..8ac8794315401d06a087dcf4614444ce98c8d12b 100644 (file)
@@ -36,6 +36,7 @@
 
 #define DVB_USB_LOG_PREFIX "anysee"
 #include "dvb-usb.h"
+#include "dvb_ca_en50221.h"
 
 #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
 #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
@@ -54,12 +55,16 @@ enum cmd {
        CMD_GET_IR_CODE         = 0x41,
        CMD_GET_HW_INFO         = 0x19,
        CMD_SMARTCARD           = 0x34,
+       CMD_CI                  = 0x37,
 };
 
 struct anysee_state {
        u8 hw; /* PCB ID */
        u8 seq;
        u8 fe_id:1; /* frondend ID */
+       u8 has_ci:1;
+       struct dvb_ca_en50221 ci;
+       unsigned long ci_cam_ready; /* jiffies */
 };
 
 #define ANYSEE_HW_507T    2 /* E30 */
@@ -69,6 +74,7 @@ struct anysee_state {
 #define ANYSEE_HW_507FA  15 /* E30 Combo Plus / E30 C Plus */
 #define ANYSEE_HW_508TC  18 /* E7 TC */
 #define ANYSEE_HW_508S2  19 /* E7 S2 */
+#define ANYSEE_HW_508T2C 20 /* E7 T2C */
 #define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */
 #define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */
 
index 9cd51ac12076eec16039c77fe6396735da9b559c..8a57ed8272dec10adfbbd989f81442ed6cc48ef9 100644 (file)
@@ -40,9 +40,8 @@
  *  We replace errornous fields by default TPS fields (the ones with value 0).
  */
 
-static uint16_t compute_tps(struct dvb_frontend_parameters *p)
+static uint16_t compute_tps(struct dtv_frontend_properties *op)
 {
-       struct dvb_ofdm_parameters *op = &p->u.ofdm;
        uint16_t tps = 0;
 
        switch (op->code_rate_HP) {
@@ -83,7 +82,7 @@ static uint16_t compute_tps(struct dvb_frontend_parameters *p)
                /* tps |= (0 << 4) */;
        }
 
-       switch (op->constellation) {
+       switch (op->modulation) {
        case QAM_16:
                tps |= (1 << 13);
                break;
@@ -119,7 +118,7 @@ static uint16_t compute_tps(struct dvb_frontend_parameters *p)
                /* tps |= (0 << 2) */;
        }
 
-       switch (op->hierarchy_information) {
+       switch (op->hierarchy) {
        case HIERARCHY_1:
                tps |= (1 << 10);
                break;
@@ -263,9 +262,9 @@ static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
        return 0;
 }
 
-static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *fep)
+static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
        struct dvbt_set_parameters_msg param;
        char result[2];
@@ -274,9 +273,20 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
        param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
        param.tps = cpu_to_le16(compute_tps(fep));
        param.freq = cpu_to_le32(fep->frequency / 1000);
-       param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
        param.flags = 0;
 
+       switch (fep->bandwidth_hz) {
+       case 8000000:
+               param.bandwidth = 0;
+               break;
+       case 7000000:
+               param.bandwidth = 1;
+               break;
+       case 6000000:
+               param.bandwidth = 2;
+               break;
+       }
+
        err = dvb_usb_generic_rw(state->d,
                        (char *)&param, sizeof(param),
                        result, sizeof(result), 0);
@@ -286,12 +296,6 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
        return (err < 0) ? err : 0;
 }
 
-static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *fep)
-{
-       return 0;
-}
-
 static void cinergyt2_fe_release(struct dvb_frontend *fe)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
@@ -316,9 +320,9 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
 
 
 static struct dvb_frontend_ops cinergyt2_fe_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = DRIVER_NAME,
-               .type                   = FE_OFDM,
                .frequency_min          = 174000000,
                .frequency_max          = 862000000,
                .frequency_stepsize     = 166667,
@@ -341,7 +345,6 @@ static struct dvb_frontend_ops cinergyt2_fe_ops = {
        .sleep                  = cinergyt2_fe_sleep,
 
        .set_frontend           = cinergyt2_fe_set_frontend,
-       .get_frontend           = cinergyt2_fe_get_frontend,
        .get_tune_settings      = cinergyt2_fe_get_tune_settings,
 
        .read_status            = cinergyt2_fe_read_status,
index 949ea1bc0aae8ae9a48982674251a4442316fed1..3940bb0f9ef62dd8b3121d3ee0a7739669581d90 100644 (file)
@@ -1067,18 +1067,17 @@ static struct dib0070_config dib7070p_dib0070_config = {
 };
 
 struct dib0700_adapter_state {
-       int (*set_param_save) (struct dvb_frontend *,
-                              struct dvb_frontend_parameters *);
+       int (*set_param_save) (struct dvb_frontend *);
 };
 
-static int dib7070_set_param_override(struct dvb_frontend *fe,
-                                     struct dvb_frontend_parameters *fep)
+static int dib7070_set_param_override(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        struct dib0700_adapter_state *state = adap->priv;
 
        u16 offset;
-       u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+       u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
        switch (band) {
        case BAND_VHF: offset = 950; break;
        default:
@@ -1087,7 +1086,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe,
 
        dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
 
-       return state->set_param_save(fe, fep);
+       return state->set_param_save(fe);
 }
 
 static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
index f313182eb9d5ed0f2b9ff7fd6f248c9f4f98df7a..81ef4b46f790f936129b849e55878e8b8a9ff89e 100644 (file)
@@ -30,7 +30,7 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif
                "if applicable for the device (default: 0=automatic/off).");
 
 struct dib0700_adapter_state {
-       int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
+       int (*set_param_save) (struct dvb_frontend *);
        const struct firmware *frontend_firmware;
 };
 
@@ -804,13 +804,14 @@ static struct dib0070_config dib7770p_dib0070_config = {
         .charge_pump = 2,
 };
 
-static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7070_set_param_override(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        struct dib0700_adapter_state *state = adap->priv;
 
        u16 offset;
-       u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+       u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
        switch (band) {
                case BAND_VHF: offset = 950; break;
                case BAND_UHF:
@@ -818,17 +819,17 @@ static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_fronte
        }
        deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
        dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
-       return state->set_param_save(fe, fep);
+       return state->set_param_save(fe);
 }
 
-static int dib7770_set_param_override(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *fep)
+static int dib7770_set_param_override(struct dvb_frontend *fe)
 {
-        struct dvb_usb_adapter *adap = fe->dvb->priv;
-        struct dib0700_adapter_state *state = adap->priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dib0700_adapter_state *state = adap->priv;
 
         u16 offset;
-        u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+        u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
         switch (band) {
         case BAND_VHF:
                  dib7000p_set_gpio(fe, 0, 0, 1);
@@ -842,7 +843,7 @@ static int dib7770_set_param_override(struct dvb_frontend *fe,
         }
         deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
         dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
-        return state->set_param_save(fe, fep);
+        return state->set_param_save(fe);
 }
 
 static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
@@ -1205,14 +1206,14 @@ static struct dib0070_config dib807x_dib0070_config[2] = {
        }
 };
 
-static int dib807x_set_param_override(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *fep)
+static int dib807x_set_param_override(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        struct dib0700_adapter_state *state = adap->priv;
 
        u16 offset = dib0070_wbd_offset(fe);
-       u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+       u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
        switch (band) {
        case BAND_VHF:
                offset += 750;
@@ -1224,7 +1225,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe,
        deb_info("WBD for DiB8000: %d\n", offset);
        dib8000_set_wbd_ref(fe, offset);
 
-       return state->set_param_save(fe, fep);
+       return state->set_param_save(fe);
 }
 
 static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
@@ -1279,7 +1280,7 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
        dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-                               0x80);
+                               0x80, 0);
 
        adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
                              &dib807x_dib8000_config[0]);
@@ -1308,7 +1309,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
        /* initialize IC 0 */
-       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
+       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
 
        adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
                              &dib807x_dib8000_config[0]);
@@ -1319,7 +1320,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
 static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
 {
        /* initialize IC 1 */
-       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
+       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
 
        adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
                              &dib807x_dib8000_config[1]);
@@ -1328,7 +1329,7 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
 }
 
 /* STK8096GP */
-struct dibx000_agc_config dib8090_agc_config[2] = {
+static struct dibx000_agc_config dib8090_agc_config[2] = {
        {
        BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
        /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
@@ -1503,22 +1504,22 @@ static struct dib0090_config dib809x_dib0090_config = {
        .fref_clock_ratio = 6,
 };
 
-static int dib8096_set_param_override(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *fep)
+static int dib8096_set_param_override(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        struct dib0700_adapter_state *state = adap->priv;
-       u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+       u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
        u16 target;
        int ret = 0;
        enum frontend_tune_state tune_state = CT_SHUTDOWN;
        u16 ltgain, rf_gain_limit;
 
-       ret = state->set_param_save(fe, fep);
+       ret = state->set_param_save(fe);
        if (ret < 0)
                return ret;
 
-       target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
+       target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
        dib8000_set_wbd_ref(fe, target);
 
 
@@ -1578,7 +1579,7 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
+       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
 
        adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
 
@@ -1629,7 +1630,7 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
        msleep(20);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
+       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
 
        adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
        if (adap->fe_adap[0].fe == NULL)
@@ -1641,6 +1642,261 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
        return fe_slave == NULL ?  -ENODEV : 0;
 }
 
+/* TFE8096P */
+static struct dibx000_agc_config dib8096p_agc_config[2] = {
+       {
+               .band_caps              = BAND_UHF,
+               /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
+                  P_agc_freq_pwm_div=1, 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=5,
+                  P_agc_write=0 */
+               .setup                  = (0 << 15) | (0 << 14) | (5 << 11)
+                       | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
+                       | (0 << 4) | (5 << 1) | (0 << 0),
+
+               .inv_gain               = 684,
+               .time_stabiliz  = 10,
+
+               .alpha_level    = 0,
+               .thlock                 = 118,
+
+               .wbd_inv                = 0,
+               .wbd_ref                = 1200,
+               .wbd_sel                = 3,
+               .wbd_alpha              = 5,
+
+               .agc1_max               = 65535,
+               .agc1_min               = 0,
+
+               .agc2_max               = 32767,
+               .agc2_min               = 0,
+
+               .agc1_pt1               = 0,
+               .agc1_pt2               = 0,
+               .agc1_pt3               = 105,
+               .agc1_slope1    = 0,
+               .agc1_slope2    = 156,
+               .agc2_pt1               = 105,
+               .agc2_pt2               = 255,
+               .agc2_slope1    = 54,
+               .agc2_slope2    = 0,
+
+               .alpha_mant             = 28,
+               .alpha_exp              = 26,
+               .beta_mant              = 31,
+               .beta_exp               = 51,
+
+               .perform_agc_softsplit = 0,
+       } , {
+               .band_caps              = BAND_FM | BAND_VHF | BAND_CBAND,
+               /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
+                  P_agc_freq_pwm_div=1, 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=5,
+                  P_agc_write=0 */
+               .setup                  = (0 << 15) | (0 << 14) | (5 << 11)
+                       | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
+                       | (0 << 4) | (5 << 1) | (0 << 0),
+
+               .inv_gain               = 732,
+               .time_stabiliz  = 10,
+
+               .alpha_level    = 0,
+               .thlock                 = 118,
+
+               .wbd_inv                = 0,
+               .wbd_ref                = 1200,
+               .wbd_sel                = 3,
+               .wbd_alpha              = 5,
+
+               .agc1_max               = 65535,
+               .agc1_min               = 0,
+
+               .agc2_max               = 32767,
+               .agc2_min               = 0,
+
+               .agc1_pt1               = 0,
+               .agc1_pt2               = 0,
+               .agc1_pt3               = 98,
+               .agc1_slope1    = 0,
+               .agc1_slope2    = 167,
+               .agc2_pt1               = 98,
+               .agc2_pt2               = 255,
+               .agc2_slope1    = 52,
+               .agc2_slope2    = 0,
+
+               .alpha_mant             = 28,
+               .alpha_exp              = 26,
+               .beta_mant              = 31,
+               .beta_exp               = 51,
+
+               .perform_agc_softsplit = 0,
+       }
+};
+
+static struct dibx000_bandwidth_config dib8096p_clock_config_12_mhz = {
+       108000, 13500,
+       1, 9, 1, 0, 0,
+       0, 0, 0, 0, 2,
+       (3 << 14) | (1 << 12) | (524 << 0),
+       (0 << 25) | 0,
+       20199729,
+       12000000,
+};
+
+static struct dib8000_config tfe8096p_dib8000_config = {
+       .output_mpeg2_in_188_bytes      = 1,
+       .hostbus_diversity                      = 1,
+       .update_lna                                     = NULL,
+
+       .agc_config_count                       = 2,
+       .agc                                            = dib8096p_agc_config,
+       .pll                                            = &dib8096p_clock_config_12_mhz,
+
+       .gpio_dir                                       = DIB8000_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val                                       = DIB8000_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos                           = DIB8000_GPIO_DEFAULT_PWM_POS,
+
+       .agc_control                            = NULL,
+       .diversity_delay                        = 48,
+       .output_mode                            = OUTMODE_MPEG2_FIFO,
+       .enMpegOutput                           = 1,
+};
+
+static struct dib0090_wbd_slope dib8096p_wbd_table[] = {
+       { 380, 81, 850, 64, 540, 4},
+       { 860, 51, 866, 21, 375, 4},
+       {1700, 0, 250, 0, 100, 6},
+       {2600, 0, 250, 0, 100, 6},
+       { 0xFFFF, 0, 0, 0, 0, 0},
+};
+
+static const struct dib0090_config tfe8096p_dib0090_config = {
+       .io.clock_khz                   = 12000,
+       .io.pll_bypass                  = 0,
+       .io.pll_range                   = 0,
+       .io.pll_prediv                  = 3,
+       .io.pll_loopdiv                 = 6,
+       .io.adc_clock_ratio             = 0,
+       .io.pll_int_loop_filt   = 0,
+       .reset                                  = dib8096p_tuner_sleep,
+       .sleep                                  = dib8096p_tuner_sleep,
+
+       .freq_offset_khz_uhf    = -143,
+       .freq_offset_khz_vhf    = -143,
+
+       .get_adc_power                  = dib8090_get_adc_power,
+
+       .clkouttobamse                  = 1,
+       .analog_output                  = 0,
+
+       .wbd_vhf_offset                 = 0,
+       .wbd_cband_offset               = 0,
+       .use_pwm_agc                    = 1,
+       .clkoutdrive                    = 0,
+
+       .fref_clock_ratio               = 1,
+
+       .wbd                                    = dib8096p_wbd_table,
+
+       .ls_cfg_pad_drv                 = 0,
+       .data_tx_drv                    = 0,
+       .low_if                                 = NULL,
+       .in_soc                                 = 1,
+       .force_cband_input              = 0,
+};
+
+struct dibx090p_adc {
+       u32 freq;                       /* RF freq MHz */
+       u32 timf;                       /* New Timf */
+       u32 pll_loopdiv;        /* New prediv */
+       u32 pll_prediv;         /* New loopdiv */
+};
+
+struct dibx090p_adc dib8090p_adc_tab[] = {
+       { 50000, 17043521, 16, 3}, /* 64 MHz */
+       {878000, 20199729, 9, 1}, /* 60 MHz */
+       {0xffffffff, 0, 0, 0}, /* 60 MHz */
+};
+
+static int dib8096p_agc_startup(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dib0700_adapter_state *state = adap->priv;
+       struct dibx000_bandwidth_config pll;
+       u16 target;
+       int better_sampling_freq = 0, ret;
+       struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0];
+
+       ret = state->set_param_save(fe);
+       if (ret < 0)
+               return ret;
+       memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
+
+       dib0090_pwm_gain_reset(fe);
+       /* dib0090_get_wbd_target is returning any possible
+          temperature compensated wbd-target */
+       target = (dib0090_get_wbd_target(fe) * 8  + 1) / 2;
+       dib8000_set_wbd_ref(fe, target);
+
+
+       while (p->frequency / 1000 > adc_table->freq) {
+               better_sampling_freq = 1;
+               adc_table++;
+       }
+
+       if ((adc_table->freq != 0xffffffff) && better_sampling_freq) {
+               pll.pll_ratio  = adc_table->pll_loopdiv;
+               pll.pll_prediv = adc_table->pll_prediv;
+               dib8000_update_pll(fe, &pll);
+               dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc_table->timf);
+       }
+       return 0;
+}
+
+static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       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);
+
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+       dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
+
+       adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
+                       &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
+
+       return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
+}
+
+static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_adapter_state *st = adap->priv;
+       struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
+
+       if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+                               &tfe8096p_dib0090_config) == NULL)
+               return -ENODEV;
+
+       dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+       st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+       adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
+       return 0;
+}
+
 /* STK9090M */
 static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
 {
@@ -1883,7 +2139,7 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
        i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
        if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
                return -ENODEV;
-       dib0700_set_i2c_speed(adap->dev, 2000);
+       dib0700_set_i2c_speed(adap->dev, 1500);
        if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
                return -ENODEV;
        release_firmware(state->frontend_firmware);
@@ -1962,7 +2218,8 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
        i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
        if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
                return -ENODEV;
-       dib0700_set_i2c_speed(adap->dev, 2000);
+
+       dib0700_set_i2c_speed(adap->dev, 1500);
        if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
                return -ENODEV;
 
@@ -1975,7 +2232,7 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
                if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
                        return -ENODEV;
                fe_slave->dvb = adap->fe_adap[0].fe->dvb;
-               dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
+               dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 1500);
                if (dib9000_firmware_post_pll_init(fe_slave) < 0)
                        return -ENODEV;
        }
@@ -2064,7 +2321,7 @@ static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_
                return 0;
 }
 
-static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7090_agc_startup(struct dvb_frontend *fe)
 {
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        struct dib0700_adapter_state *state = adap->priv;
@@ -2073,13 +2330,13 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para
        struct dib7090p_best_adc adc;
        int ret;
 
-       ret = state->set_param_save(fe, fep);
+       ret = state->set_param_save(fe);
        if (ret < 0)
                return ret;
 
        memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
        dib0090_pwm_gain_reset(fe);
-       target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2;
+       target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
        dib7000p_set_wbd_ref(fe, target);
 
        if (dib7090p_get_best_sampling(fe, &adc) == 0) {
@@ -2092,6 +2349,49 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para
        return 0;
 }
 
+static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
+{
+       deb_info("AGC restart callback: %d", restart);
+       if (restart == 0) /* before AGC startup */
+               dib0090_set_dc_servo(fe, 1);
+       return 0;
+}
+
+static int dib7090e_update_lna(struct dvb_frontend *fe, u16 agc_global)
+{
+       u16 agc1 = 0, agc2, wbd = 0, wbd_target, wbd_offset, threshold_agc1;
+       s16 wbd_delta;
+
+       if ((fe->dtv_property_cache.frequency) < 400000000)
+               threshold_agc1 = 25000;
+       else
+               threshold_agc1 = 30000;
+
+       wbd_target = (dib0090_get_wbd_target(fe)*8+1)/2;
+       wbd_offset = dib0090_get_wbd_offset(fe);
+       dib7000p_get_agc_values(fe, NULL, &agc1, &agc2, &wbd);
+       wbd_delta = (s16)wbd - (((s16)wbd_offset+10)*4) ;
+
+       deb_info("update lna, agc_global=%d agc1=%d agc2=%d",
+                       agc_global, agc1, agc2);
+       deb_info("update lna, wbd=%d wbd target=%d wbd offset=%d wbd delta=%d",
+                       wbd, wbd_target, wbd_offset, wbd_delta);
+
+       if ((agc1 < threshold_agc1) && (wbd_delta > 0)) {
+               dib0090_set_switch(fe, 1, 1, 1);
+               dib0090_set_vga(fe, 0);
+               dib0090_update_rframp_7090(fe, 0);
+               dib0090_update_tuning_table_7090(fe, 0);
+       } else {
+               dib0090_set_vga(fe, 1);
+               dib0090_update_rframp_7090(fe, 1);
+               dib0090_update_tuning_table_7090(fe, 1);
+               dib0090_set_switch(fe, 0, 0, 0);
+       }
+
+       return 0;
+}
+
 static struct dib0090_wbd_slope dib7090_wbd_table[] = {
        { 380,   81, 850, 64, 540,  4},
        { 860,   51, 866, 21,  375, 4},
@@ -2100,7 +2400,16 @@ static struct dib0090_wbd_slope dib7090_wbd_table[] = {
        { 0xFFFF, 0,   0, 0,   0,   0},
 };
 
-struct dibx000_agc_config dib7090_agc_config[2] = {
+static struct dib0090_wbd_slope dib7090e_wbd_table[] = {
+       { 380,   81, 850, 64, 540,      4},
+       { 700,   51, 866, 21,  320,     4},
+       { 860,   48, 666, 18,  330,     6},
+       {1700,    0, 250, 0,   100, 6},
+       {2600,    0, 250, 0,   100, 6},
+       { 0xFFFF, 0,   0, 0,   0,       0},
+};
+
+static struct dibx000_agc_config dib7090_agc_config[2] = {
        {
                .band_caps      = BAND_UHF,
                /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
@@ -2278,6 +2587,34 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
        }
 };
 
+static struct dib7000p_config tfe7090e_dib7000p_config = {
+       .output_mpeg2_in_188_bytes  = 1,
+       .hostbus_diversity                      = 1,
+       .tuner_is_baseband                      = 1,
+       .update_lna                                     = dib7090e_update_lna,
+
+       .agc_config_count                       = 2,
+       .agc                                            = dib7090_agc_config,
+
+       .bw                                                     = &dib7090_clock_config_12_mhz,
+
+       .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                            = dib7090_agc_restart,
+
+       .spur_protect                           = 0,
+       .disable_sample_and_hold        = 0,
+       .enable_current_mirror          = 0,
+       .diversity_delay                        = 0,
+
+       .output_mode                            = OUTMODE_MPEG2_FIFO,
+       .enMpegOutput                           = 1,
+};
+
 static const struct dib0090_config nim7090_dib0090_config = {
        .io.clock_khz = 12000,
        .io.pll_bypass = 0,
@@ -2312,6 +2649,107 @@ static const struct dib0090_config nim7090_dib0090_config = {
        .in_soc = 1,
 };
 
+static const struct dib0090_config tfe7090e_dib0090_config = {
+       .io.clock_khz = 12000,
+       .io.pll_bypass = 0,
+       .io.pll_range = 0,
+       .io.pll_prediv = 3,
+       .io.pll_loopdiv = 6,
+       .io.adc_clock_ratio = 0,
+       .io.pll_int_loop_filt = 0,
+       .reset = dib7090_tuner_sleep,
+       .sleep = dib7090_tuner_sleep,
+
+       .freq_offset_khz_uhf = 0,
+       .freq_offset_khz_vhf = 0,
+
+       .get_adc_power = dib7090_get_adc_power,
+
+       .clkouttobamse = 1,
+       .analog_output = 0,
+
+       .wbd_vhf_offset = 0,
+       .wbd_cband_offset = 0,
+       .use_pwm_agc = 1,
+       .clkoutdrive = 0,
+
+       .fref_clock_ratio = 0,
+
+       .wbd = dib7090e_wbd_table,
+
+       .ls_cfg_pad_drv = 0,
+       .data_tx_drv = 0,
+       .low_if = NULL,
+       .in_soc = 1,
+       .force_cband_input = 1,
+       .is_dib7090e = 1,
+};
+
+static struct dib7000p_config tfe7790e_dib7000p_config = {
+       .output_mpeg2_in_188_bytes  = 1,
+       .hostbus_diversity                      = 1,
+       .tuner_is_baseband                      = 1,
+       .update_lna                                     = dib7090e_update_lna,
+
+       .agc_config_count                       = 2,
+       .agc                                            = dib7090_agc_config,
+
+       .bw                                                     = &dib7090_clock_config_12_mhz,
+
+       .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                            = dib7090_agc_restart,
+
+       .spur_protect                           = 0,
+       .disable_sample_and_hold        = 0,
+       .enable_current_mirror          = 0,
+       .diversity_delay                        = 0,
+
+       .output_mode                            = OUTMODE_MPEG2_PAR_GATED_CLK,
+       .enMpegOutput                           = 1,
+};
+
+static const struct dib0090_config tfe7790e_dib0090_config = {
+       .io.clock_khz = 12000,
+       .io.pll_bypass = 0,
+       .io.pll_range = 0,
+       .io.pll_prediv = 3,
+       .io.pll_loopdiv = 6,
+       .io.adc_clock_ratio = 0,
+       .io.pll_int_loop_filt = 0,
+       .reset = dib7090_tuner_sleep,
+       .sleep = dib7090_tuner_sleep,
+
+       .freq_offset_khz_uhf = 0,
+       .freq_offset_khz_vhf = 0,
+
+       .get_adc_power = dib7090_get_adc_power,
+
+       .clkouttobamse = 1,
+       .analog_output = 0,
+
+       .wbd_vhf_offset = 0,
+       .wbd_cband_offset = 0,
+       .use_pwm_agc = 1,
+       .clkoutdrive = 0,
+
+       .fref_clock_ratio = 0,
+
+       .wbd = dib7090e_wbd_table,
+
+       .ls_cfg_pad_drv = 0,
+       .data_tx_drv = 0,
+       .low_if = NULL,
+       .in_soc = 1,
+       .force_cband_input = 1,
+       .is_dib7090e = 1,
+       .force_crystal_mode = 1,
+};
+
 static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
        {
                .io.clock_khz = 12000,
@@ -2504,6 +2942,97 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
+static int tfe7090e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       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(20);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+       if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+                               1, 0x10, &tfe7090e_dib7000p_config) != 0) {
+               err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+                               __func__);
+               return -ENODEV;
+       }
+       adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+                       0x80, &tfe7090e_dib7000p_config);
+
+       return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
+}
+
+static int tfe7790e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+
+       /* The TFE7790E requires the dib0700 to not be in master mode */
+       st->disable_streaming_master_mode = 1;
+
+       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(20);
+       dib0700_ctrl_clock(adap->dev, 72, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+       if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+                               1, 0x10, &tfe7790e_dib7000p_config) != 0) {
+               err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+                               __func__);
+               return -ENODEV;
+       }
+       adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+                       0x80, &tfe7790e_dib7000p_config);
+
+       return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
+}
+
+static int tfe7790e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_adapter_state *st = adap->priv;
+       struct i2c_adapter *tun_i2c =
+               dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+
+       if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+                               &tfe7790e_dib0090_config) == NULL)
+               return -ENODEV;
+
+       dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+       st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+       adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+       return 0;
+}
+
+static int tfe7090e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_adapter_state *st = adap->priv;
+       struct i2c_adapter *tun_i2c =
+               dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+
+       if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+                               &tfe7090e_dib0090_config) == NULL)
+               return -ENODEV;
+
+       dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+       st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+       adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+       return 0;
+}
+
 /* STK7070PD */
 static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
        {
@@ -2960,6 +3489,9 @@ struct usb_device_id dib0700_usb_id_table[] = {
 /* 75 */{ USB_DEVICE(USB_VID_MEDION,    USB_PID_CREATIX_CTX1921) },
        { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E) },
        { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E_SE) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090E) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7790E) },
+/* 80 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE8096P) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -4015,6 +4547,127 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { NULL },
                        },
                },
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol  = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .num_frontends = 1,
+                               .fe = {{
+                                       .caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+                                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                                       .pid_filter_count = 32,
+                                       .pid_filter = stk70x0p_pid_filter,
+                                       .pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+                                       .frontend_attach  = tfe7090e_frontend_attach,
+                                       .tuner_attach     = tfe7090e_tuner_attach,
+
+                                       DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+                               } },
+
+                               .size_of_priv =
+                                       sizeof(struct dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "DiBcom TFE7090E reference design",
+                               { &dib0700_usb_id_table[78], NULL },
+                               { NULL },
+                       },
+               },
+
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol  = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .num_frontends = 1,
+                               .fe = {{
+                                       .caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+                                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                                       .pid_filter_count = 32,
+                                       .pid_filter = stk70x0p_pid_filter,
+                                       .pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+                                       .frontend_attach  = tfe7790e_frontend_attach,
+                                       .tuner_attach     = tfe7790e_tuner_attach,
+
+                                       DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+                               } },
+
+                               .size_of_priv =
+                                       sizeof(struct dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "DiBcom TFE7790E reference design",
+                               { &dib0700_usb_id_table[79], NULL },
+                               { NULL },
+                       },
+               },
+
+               .rc.core = {
+                       .rc_interval      = DEFAULT_RC_INTERVAL,
+                       .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+                       .module_name      = "dib0700",
+                       .rc_query         = dib0700_rc_query_old_firmware,
+                       .allowed_protos   = RC_TYPE_RC5 |
+                                           RC_TYPE_RC6 |
+                                           RC_TYPE_NEC,
+                       .change_protocol  = dib0700_change_protocol,
+               },
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .num_frontends = 1,
+                               .fe = {{
+                                       .caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+                                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                                       .pid_filter_count = 32,
+                                       .pid_filter = stk80xx_pid_filter,
+                                       .pid_filter_ctrl = stk80xx_pid_filter_ctrl,
+                                       .frontend_attach  = tfe8096p_frontend_attach,
+                                       .tuner_attach     = tfe8096p_tuner_attach,
+
+                                       DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+                               } },
+
+                               .size_of_priv =
+                                       sizeof(struct dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 1,
+               .devices = {
+                       {   "DiBcom TFE8096P reference design",
+                               { &dib0700_usb_id_table[80], NULL },
+                               { NULL },
+                       },
+               },
+
                .rc.core = {
                        .rc_interval      = DEFAULT_RC_INTERVAL,
                        .rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
index 0a9a79820f261402c0cfa8778f3f379aa54bde66..ff34419a4c88438ca74ac0eac19180d9fbeafd07 100644 (file)
@@ -118,12 +118,12 @@ static struct mt352_config digitv_mt352_config = {
        .demod_init = digitv_mt352_demod_init,
 };
 
-static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
 {
        struct dvb_usb_adapter *adap = fe->dvb->priv;
        u8 b[5];
 
-       fe->ops.tuner_ops.calc_regs(fe, fep, b, sizeof(b));
+       fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
index 17413adec7a1fbd92199c97d0a45f2dfa37e8875..3d81daa4917229ff3c92a8d7c59dc20eae34f8cc 100644 (file)
@@ -16,7 +16,7 @@ struct dtt200u_fe_state {
 
        fe_status_t stat;
 
-       struct dvb_frontend_parameters fep;
+       struct dtv_frontend_properties fep;
        struct dvb_frontend frontend;
 };
 
@@ -100,22 +100,27 @@ static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fron
        return 0;
 }
 
-static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dtt200u_fe_state *state = fe->demodulator_priv;
        int i;
        fe_status_t st;
        u16 freq = fep->frequency / 250000;
        u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
 
-       switch (fep->u.ofdm.bandwidth) {
-               case BANDWIDTH_8_MHZ: bwbuf[1] = 8; break;
-               case BANDWIDTH_7_MHZ: bwbuf[1] = 7; break;
-               case BANDWIDTH_6_MHZ: bwbuf[1] = 6; break;
-               case BANDWIDTH_AUTO: return -EOPNOTSUPP;
-               default:
-                       return -EINVAL;
+       switch (fep->bandwidth_hz) {
+       case 8000000:
+               bwbuf[1] = 8;
+               break;
+       case 7000000:
+               bwbuf[1] = 7;
+               break;
+       case 6000000:
+               bwbuf[1] = 6;
+               break;
+       default:
+               return -EINVAL;
        }
 
        dvb_usb_generic_write(state->d,bwbuf,2);
@@ -134,11 +139,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
-static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int dtt200u_fe_get_frontend(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
+       memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
        return 0;
 }
 
@@ -172,9 +177,9 @@ error:
 }
 
 static struct dvb_frontend_ops dtt200u_fe_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "WideView USB DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 44250000,
                .frequency_max          = 867250000,
                .frequency_stepsize     = 250000,
index ba4a7517354ff96f52e94f4830c1c0a1c2efc137..ddf282f355b3c78f9f71608f4f445f196d68d3fc 100644 (file)
@@ -141,11 +141,17 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
                goto err_dmx_dev;
        }
 
-       dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+       if ((ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net,
+                                               &adap->demux.dmx)) < 0) {
+               err("dvb_net_init failed: error %d",ret);
+               goto err_net_init;
+       }
 
        adap->state |= DVB_USB_ADAP_STATE_DVB;
        return 0;
 
+err_net_init:
+       dvb_dmxdev_release(&adap->dmxdev);
 err_dmx_dev:
        dvb_dmx_release(&adap->demux);
 err_dmx:
index 2d08c9b5128a2759a60f04e7a3bf9e31cd23fd88..d390ddaa5a53f7a6daf37bf5d341c965814a6214 100644 (file)
 #define USB_PID_DIBCOM_STK807XPVR                      0x1f98
 #define USB_PID_DIBCOM_STK8096GP                        0x1fa0
 #define USB_PID_DIBCOM_NIM8096MD                        0x1fa8
+#define USB_PID_DIBCOM_TFE8096P                                0x1f9C
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD                        0x2131
 #define USB_PID_DIBCOM_STK7770P                                0x1e80
 #define USB_PID_DIBCOM_NIM7090                         0x1bb2
 #define USB_PID_DIBCOM_TFE7090PVR                      0x1bb4
+#define USB_PID_DIBCOM_TFE7090E                                0x1bb7
+#define USB_PID_DIBCOM_TFE7790E                                0x1e6e
 #define USB_PID_DIBCOM_NIM9090M                                0x2383
 #define USB_PID_DIBCOM_NIM9090MD                       0x2384
 #define USB_PID_DPOSH_M9206_COLD                       0x9206
 #define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
 #define USB_PID_INTEL_CE9500                           0x9500
 #define USB_PID_ITETECH_IT9135                         0x9135
+#define USB_PID_ITETECH_IT9135_9005                    0x9005
+#define USB_PID_ITETECH_IT9135_9006                    0x9006
 #define USB_PID_KWORLD_399U                            0xe399
 #define USB_PID_KWORLD_399U_2                          0xe400
 #define USB_PID_KWORLD_395U                            0xe396
 #define USB_PID_TVWAY_PLUS                             0x0002
 #define USB_PID_SVEON_STV20                            0xe39d
 #define USB_PID_SVEON_STV22                            0xe401
+#define USB_PID_SVEON_STV22_IT9137                     0xe411
 #define USB_PID_AZUREWAVE_AZ6027                       0x3275
 #define USB_PID_TERRATEC_DVBS2CI_V1                    0x10a4
 #define USB_PID_TERRATEC_DVBS2CI_V2                    0x10ac
index ff941d20e6b7a1eeb7b2d4fd43740a9422c9f671..451c5a7adfb2da284c02593f29801e87909fe403 100644 (file)
@@ -1435,22 +1435,40 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        return 0;
 }
 
+enum dw2102_table_entry {
+       CYPRESS_DW2102,
+       CYPRESS_DW2101,
+       CYPRESS_DW2104,
+       TEVII_S650,
+       TERRATEC_CINERGY_S,
+       CYPRESS_DW3101,
+       TEVII_S630,
+       PROF_1100,
+       TEVII_S660,
+       PROF_7500,
+       GENIATECH_SU3000,
+       TERRATEC_CINERGY_S2,
+       TEVII_S480_1,
+       TEVII_S480_2,
+       X3M_SPC1400HD,
+};
+
 static struct usb_device_id dw2102_table[] = {
-       {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
-       {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
-       {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
-       {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
-       {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
-       {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
-       {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
-       {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
-       {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
-       {USB_DEVICE(0x3034, 0x7500)},
-       {USB_DEVICE(0x1f4d, 0x3000)},
-       {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
-       {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
-       {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
-       {USB_DEVICE(0x1f4d, 0x3100)},
+       [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
+       [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+       [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
+       [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
+       [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
+       [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
+       [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
+       [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
+       [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
+       [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
+       [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
+       [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
+       [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
+       [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
+       [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
        { }
 };
 
@@ -1610,15 +1628,15 @@ static struct dvb_usb_device_properties dw2102_properties = {
        .num_device_descs = 3,
        .devices = {
                {"DVBWorld DVB-S 2102 USB2.0",
-                       {&dw2102_table[0], NULL},
+                       {&dw2102_table[CYPRESS_DW2102], NULL},
                        {NULL},
                },
                {"DVBWorld DVB-S 2101 USB2.0",
-                       {&dw2102_table[1], NULL},
+                       {&dw2102_table[CYPRESS_DW2101], NULL},
                        {NULL},
                },
                {"TerraTec Cinergy S USB",
-                       {&dw2102_table[4], NULL},
+                       {&dw2102_table[TERRATEC_CINERGY_S], NULL},
                        {NULL},
                },
        }
@@ -1664,11 +1682,11 @@ static struct dvb_usb_device_properties dw2104_properties = {
        .num_device_descs = 2,
        .devices = {
                { "DVBWorld DW2104 USB2.0",
-                       {&dw2102_table[2], NULL},
+                       {&dw2102_table[CYPRESS_DW2104], NULL},
                        {NULL},
                },
                { "TeVii S650 USB2.0",
-                       {&dw2102_table[3], NULL},
+                       {&dw2102_table[TEVII_S650], NULL},
                        {NULL},
                },
        }
@@ -1715,7 +1733,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
        .num_device_descs = 1,
        .devices = {
                { "DVBWorld DVB-C 3101 USB2.0",
-                       {&dw2102_table[5], NULL},
+                       {&dw2102_table[CYPRESS_DW3101], NULL},
                        {NULL},
                },
        }
@@ -1761,7 +1779,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
        .num_device_descs = 1,
        .devices = {
                {"TeVii S630 USB",
-                       {&dw2102_table[6], NULL},
+                       {&dw2102_table[TEVII_S630], NULL},
                        {NULL},
                },
        }
@@ -1770,33 +1788,33 @@ static struct dvb_usb_device_properties s6x0_properties = {
 struct dvb_usb_device_properties *p1100;
 static struct dvb_usb_device_description d1100 = {
        "Prof 1100 USB ",
-       {&dw2102_table[7], NULL},
+       {&dw2102_table[PROF_1100], NULL},
        {NULL},
 };
 
 struct dvb_usb_device_properties *s660;
 static struct dvb_usb_device_description d660 = {
        "TeVii S660 USB",
-       {&dw2102_table[8], NULL},
+       {&dw2102_table[TEVII_S660], NULL},
        {NULL},
 };
 
 static struct dvb_usb_device_description d480_1 = {
        "TeVii S480.1 USB",
-       {&dw2102_table[12], NULL},
+       {&dw2102_table[TEVII_S480_1], NULL},
        {NULL},
 };
 
 static struct dvb_usb_device_description d480_2 = {
        "TeVii S480.2 USB",
-       {&dw2102_table[13], NULL},
+       {&dw2102_table[TEVII_S480_2], NULL},
        {NULL},
 };
 
 struct dvb_usb_device_properties *p7500;
 static struct dvb_usb_device_description d7500 = {
        "Prof 7500 USB DVB-S2",
-       {&dw2102_table[9], NULL},
+       {&dw2102_table[PROF_7500], NULL},
        {NULL},
 };
 
@@ -1842,15 +1860,15 @@ static struct dvb_usb_device_properties su3000_properties = {
        .num_device_descs = 3,
        .devices = {
                { "SU3000HD DVB-S USB2.0",
-                       { &dw2102_table[10], NULL },
+                       { &dw2102_table[GENIATECH_SU3000], NULL },
                        { NULL },
                },
                { "Terratec Cinergy S2 USB HD",
-                       { &dw2102_table[11], NULL },
+                       { &dw2102_table[TERRATEC_CINERGY_S2], NULL },
                        { NULL },
                },
                { "X3M TV SPC1400HD PCI",
-                       { &dw2102_table[14], NULL },
+                       { &dw2102_table[X3M_SPC1400HD], NULL },
                        { NULL },
                },
        }
@@ -1859,12 +1877,11 @@ static struct dvb_usb_device_properties su3000_properties = {
 static int dw2102_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+       p1100 = kmemdup(&s6x0_properties,
+                       sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
        if (!p1100)
                return -ENOMEM;
        /* copy default structure */
-       memcpy(p1100, &s6x0_properties,
-                       sizeof(struct dvb_usb_device_properties));
        /* fill only different fields */
        p1100->firmware = "dvb-usb-p1100.fw";
        p1100->devices[0] = d1100;
@@ -1872,13 +1889,12 @@ static int dw2102_probe(struct usb_interface *intf,
        p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
        p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
 
-       s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+       s660 = kmemdup(&s6x0_properties,
+                      sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
        if (!s660) {
                kfree(p1100);
                return -ENOMEM;
        }
-       memcpy(s660, &s6x0_properties,
-                       sizeof(struct dvb_usb_device_properties));
        s660->firmware = "dvb-usb-s660.fw";
        s660->num_device_descs = 3;
        s660->devices[0] = d660;
@@ -1886,14 +1902,13 @@ static int dw2102_probe(struct usb_interface *intf,
        s660->devices[2] = d480_2;
        s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
 
-       p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+       p7500 = kmemdup(&s6x0_properties,
+                       sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
        if (!p7500) {
                kfree(p1100);
                kfree(s660);
                return -ENOMEM;
        }
-       memcpy(p7500, &s6x0_properties,
-                       sizeof(struct dvb_usb_device_properties));
        p7500->firmware = "dvb-usb-p7500.fw";
        p7500->devices[0] = d7500;
        p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
index 015b4e8af1a58d950ca446f57da894c82ad9cea1..90a70c66a96e12a019654a6f3ff74934fefde85c 100644 (file)
@@ -282,23 +282,24 @@ static int jdvbt90502_set_property(struct dvb_frontend *fe,
        return r;
 }
 
-static int jdvbt90502_get_frontend(struct dvb_frontend *fe,
-                                  struct dvb_frontend_parameters *p)
+static int jdvbt90502_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        p->inversion = INVERSION_AUTO;
-       p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
-       p->u.ofdm.code_rate_HP = FEC_AUTO;
-       p->u.ofdm.code_rate_LP = FEC_AUTO;
-       p->u.ofdm.constellation = QAM_64;
-       p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
-       p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
-       p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
+       p->bandwidth_hz = 6000000;
+       p->code_rate_HP = FEC_AUTO;
+       p->code_rate_LP = FEC_AUTO;
+       p->modulation = QAM_64;
+       p->transmission_mode = TRANSMISSION_MODE_AUTO;
+       p->guard_interval = GUARD_INTERVAL_AUTO;
+       p->hierarchy = HIERARCHY_AUTO;
        return 0;
 }
 
-static int jdvbt90502_set_frontend(struct dvb_frontend *fe,
-                                  struct dvb_frontend_parameters *p)
+static int jdvbt90502_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
        /**
         * NOTE: ignore all the parameters except frequency.
         *       others should be fixed to the proper value for ISDB-T,
@@ -438,14 +439,12 @@ error:
 }
 
 static struct dvb_frontend_ops jdvbt90502_ops = {
-
+       .delsys = { SYS_ISDBT },
        .info = {
                .name                   = "Comtech JDVBT90502 ISDB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 473000000, /* UHF 13ch, center */
                .frequency_max          = 767142857, /* UHF 62ch, center */
-               .frequency_stepsize     = JDVBT90502_PLL_CLK /
-                                                       JDVBT90502_PLL_DIVIDER,
+               .frequency_stepsize     = JDVBT90502_PLL_CLK / JDVBT90502_PLL_DIVIDER,
                .frequency_tolerance    = 0,
 
                /* NOTE: this driver ignores all parameters but frequency. */
index 5426267980c7567af09ed9646e58533e76e8df12..67957dd99ede5bf4bf70e06c287f56478728c5b1 100644 (file)
@@ -113,28 +113,12 @@ static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
        return 0;
 }
 
-static int gp8psk_fe_set_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       deb_fe("%s(..)\n", __func__);
-       return 0;
-}
-
-static int gp8psk_fe_get_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       deb_fe("%s(..)\n", __func__);
-       return 0;
-}
-
-
-static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
 {
        struct gp8psk_fe_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u8 cmd[10];
-       u32 freq = fep->frequency * 1000;
+       u32 freq = c->frequency * 1000;
        int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
 
        deb_fe("%s()\n", __func__);
@@ -342,9 +326,9 @@ success:
 
 
 static struct dvb_frontend_ops gp8psk_fe_ops = {
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "Genpix DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 800000,
                .frequency_max          = 2250000,
                .frequency_stepsize     = 100,
@@ -366,8 +350,6 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
        .init = NULL,
        .sleep = NULL,
 
-       .set_property = gp8psk_fe_set_property,
-       .get_property = gp8psk_fe_get_property,
        .set_frontend = gp8psk_fe_set_frontend,
 
        .get_tune_settings = gp8psk_fe_get_tune_settings,
index 67094b879bb40d812600e33d0954fe5615280727..9f01cd7a6e3fbd6d67bf8be402b23b0413ee7ffc 100644 (file)
@@ -52,42 +52,59 @@ static int pid_filter;
 module_param_named(pid, pid_filter, int, 0644);
 MODULE_PARM_DESC(pid, "set default 0=on 1=off");
 
+static int dvb_usb_it913x_firmware;
+module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644);
+MODULE_PARM_DESC(firmware, "set firmware 0=auto 1=IT9137 2=IT9135V1");
+
+
 int cmd_counter;
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct it913x_state {
        u8 id;
-};
-
-struct ite_config {
-       u8 chip_ver;
-       u16 chip_type;
-       u32 firmware;
-       u8 tuner_id_0;
-       u8 tuner_id_1;
-       u8 dual_mode;
+       struct ite_config it913x_config;
 };
 
 struct ite_config it913x_config;
 
+#define IT913X_RETRY   10
+#define IT913X_SND_TIMEOUT     100
+#define IT913X_RCV_TIMEOUT     200
+
 static int it913x_bulk_write(struct usb_device *dev,
                                u8 *snd, int len, u8 pipe)
 {
-       int ret, actual_l;
+       int ret, actual_l, i;
+
+       for (i = 0; i < IT913X_RETRY; i++) {
+               ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
+                               snd, len , &actual_l, IT913X_SND_TIMEOUT);
+               if (ret == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+                       break;
+       }
+
+       if (len != actual_l && ret == 0)
+               ret = -EAGAIN;
 
-       ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-                               snd, len , &actual_l, 100);
        return ret;
 }
 
 static int it913x_bulk_read(struct usb_device *dev,
                                u8 *rev, int len, u8 pipe)
 {
-       int ret, actual_l;
+       int ret, actual_l, i;
+
+       for (i = 0; i < IT913X_RETRY; i++) {
+               ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
+                                rev, len , &actual_l, IT913X_RCV_TIMEOUT);
+               if (ret == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+                       break;
+       }
+
+       if (len != actual_l && ret == 0)
+               ret = -EAGAIN;
 
-       ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-                                rev, len , &actual_l, 200);
        return ret;
 }
 
@@ -100,7 +117,7 @@ static u16 check_sum(u8 *p, u8 len)
        return ~sum;
 }
 
-static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+static int it913x_usb_talk(struct usb_device *udev, u8 mode, u8 pro,
                        u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
 {
        int ret = 0, i, buf_size = 1;
@@ -159,22 +176,41 @@ static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
        buff[buf_size++] = (chk_sum & 0xff);
 
        ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
+       if (ret < 0)
+               goto error;
 
-       ret |= it913x_bulk_read(udev, buff, (mode & 1) ?
+       ret = it913x_bulk_read(udev, buff, (mode & 1) ?
                        5 : len + 5 , 0x01);
+       if (ret < 0)
+               goto error;
 
        rlen = (mode & 0x1) ? 0x1 : len;
 
        if (mode & 1)
-               ret |= buff[2];
+               ret = buff[2];
        else
                memcpy(data, &buff[3], rlen);
 
        cmd_counter++;
 
-       kfree(buff);
+error: kfree(buff);
 
-       return (ret < 0) ? -ENODEV : 0;
+       return ret;
+}
+
+static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+                       u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
+{
+       int ret, i;
+
+       for (i = 0; i < IT913X_RETRY; i++) {
+               ret = it913x_usb_talk(udev, mode, pro,
+                       cmd, reg, addr, data, len);
+               if (ret != -EAGAIN)
+                       break;
+       }
+
+       return ret;
 }
 
 static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
@@ -223,15 +259,15 @@ static u32 it913x_query(struct usb_device *udev, u8 pro)
 
 static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-       int ret = 0;
+       struct usb_device *udev = adap->dev->udev;
+       int ret;
        u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
 
        if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
                        return -EAGAIN;
        deb_info(1, "PID_C  (%02x)", onoff);
 
-       if (!onoff)
-               ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+       ret = it913x_wr_reg(udev, pro, PID_EN, onoff);
 
        mutex_unlock(&adap->dev->i2c_mutex);
        return ret;
@@ -241,27 +277,20 @@ static int it913x_pid_filter(struct dvb_usb_adapter *adap,
                int index, u16 pid, int onoff)
 {
        struct usb_device *udev = adap->dev->udev;
-       int ret = 0;
+       int ret;
        u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
 
-       if (pid_filter > 0)
-               return 0;
-
        if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
                        return -EAGAIN;
        deb_info(1, "PID_F  (%02x)", onoff);
-       if (onoff) {
-               ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
-
-               ret |= it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
 
-               ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
+       ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
 
-               ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
+       ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
 
-               ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
+       ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
 
-       }
+       ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
 
        mutex_unlock(&adap->dev->i2c_mutex);
        return 0;
@@ -337,15 +366,73 @@ static int it913x_rc_query(struct dvb_usb_device *d)
 
        if ((ibuf[2] + ibuf[3]) == 0xff) {
                key = ibuf[2];
-               key += ibuf[0] << 8;
-               deb_info(1, "INT Key =%08x", key);
+               key += ibuf[0] << 16;
+               key += ibuf[1] << 8;
+               deb_info(1, "NEC Extended Key =%08x", key);
                if (d->rc_dev != NULL)
                        rc_keydown(d->rc_dev, key, 0);
        }
+
        mutex_unlock(&d->i2c_mutex);
 
        return ret;
 }
+
+/* Firmware sets raw */
+const char fw_it9135_v1[] = "dvb-usb-it9135-01.fw";
+const char fw_it9135_v2[] = "dvb-usb-it9135-02.fw";
+const char fw_it9137[] = "dvb-usb-it9137-01.fw";
+
+static int ite_firmware_select(struct usb_device *udev,
+       struct dvb_usb_device_properties *props)
+{
+       int sw;
+       /* auto switch */
+       if (le16_to_cpu(udev->descriptor.idProduct) ==
+                       USB_PID_ITETECH_IT9135)
+               sw = IT9135_V1_FW;
+       else if (le16_to_cpu(udev->descriptor.idProduct) ==
+                       USB_PID_ITETECH_IT9135_9005)
+               sw = IT9135_V1_FW;
+       else if (le16_to_cpu(udev->descriptor.idProduct) ==
+                       USB_PID_ITETECH_IT9135_9006) {
+               sw = IT9135_V2_FW;
+               if (it913x_config.tuner_id_0 == 0)
+                       it913x_config.tuner_id_0 = IT9135_60;
+       } else
+               sw = IT9137_FW;
+
+       /* force switch */
+       if (dvb_usb_it913x_firmware != IT9135_AUTO)
+               sw = dvb_usb_it913x_firmware;
+
+       switch (sw) {
+       case IT9135_V1_FW:
+               it913x_config.firmware_ver = 1;
+               it913x_config.adc_x2 = 1;
+               props->firmware = fw_it9135_v1;
+               break;
+       case IT9135_V2_FW:
+               it913x_config.firmware_ver = 1;
+               it913x_config.adc_x2 = 1;
+               props->firmware = fw_it9135_v2;
+               break;
+       case IT9137_FW:
+       default:
+               it913x_config.firmware_ver = 0;
+               it913x_config.adc_x2 = 0;
+               props->firmware = fw_it9137;
+       }
+
+       return 0;
+}
+
+#define TS_MPEG_PKT_SIZE       188
+#define EP_LOW                 21
+#define TS_BUFFER_SIZE_PID     (EP_LOW*TS_MPEG_PKT_SIZE)
+#define EP_HIGH                        348
+#define TS_BUFFER_SIZE_MAX     (EP_HIGH*TS_MPEG_PKT_SIZE)
+
 static int it913x_identify_state(struct usb_device *udev,
                struct dvb_usb_device_properties *props,
                struct dvb_usb_device_description **desc,
@@ -359,6 +446,19 @@ static int it913x_identify_state(struct usb_device *udev,
        /* checnk for dual mode */
        it913x_config.dual_mode =  it913x_read_reg(udev, 0x49c5);
 
+       if (udev->speed != USB_SPEED_HIGH) {
+               props->adapter[0].fe[0].pid_filter_count = 5;
+               info("USB 1 low speed mode - connect to USB 2 port");
+               if (pid_filter > 0)
+                       pid_filter = 0;
+               if (it913x_config.dual_mode) {
+                       it913x_config.dual_mode = 0;
+                       info("Dual mode not supported in USB 1");
+               }
+       } else /* For replugging */
+               if(props->adapter[0].fe[0].pid_filter_count == 5)
+                       props->adapter[0].fe[0].pid_filter_count = 31;
+
        /* TODO different remotes */
        remote = it913x_read_reg(udev, 0x49ac); /* Remote */
        if (remote == 0)
@@ -370,6 +470,28 @@ static int it913x_identify_state(struct usb_device *udev,
        info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
                , remote, it913x_config.tuner_id_0);
 
+       /* Select Stream Buffer Size and pid filter option*/
+       if (pid_filter) {
+               props->adapter[0].fe[0].stream.u.bulk.buffersize =
+                       TS_BUFFER_SIZE_MAX;
+               props->adapter[0].fe[0].caps &=
+                       ~DVB_USB_ADAP_NEED_PID_FILTERING;
+       } else
+               props->adapter[0].fe[0].stream.u.bulk.buffersize =
+                       TS_BUFFER_SIZE_PID;
+
+       if (it913x_config.dual_mode) {
+               props->adapter[1].fe[0].stream.u.bulk.buffersize =
+                       props->adapter[0].fe[0].stream.u.bulk.buffersize;
+               props->num_adapters = 2;
+               if (pid_filter)
+                       props->adapter[1].fe[0].caps =
+                               props->adapter[0].fe[0].caps;
+       } else
+               props->num_adapters = 1;
+
+       ret = ite_firmware_select(udev, props);
+
        if (firm_no > 0) {
                *cold = 0;
                return 0;
@@ -391,18 +513,22 @@ static int it913x_identify_state(struct usb_device *udev,
                                ret = it913x_wr_reg(udev, DEV_0,
                                        GPIOH1_O, 0x0);
                }
-               props->num_adapters = 2;
-       } else
-               props->num_adapters = 1;
+       }
 
        reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
 
        if (it913x_config.dual_mode) {
                ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
-               ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
+               if (it913x_config.firmware_ver == 1)
+                       ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x1);
+               else
+                       ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
        } else {
                ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
-               ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
+               if (it913x_config.firmware_ver == 1)
+                       ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x0);
+               else
+                       ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
        }
 
        *cold = 1;
@@ -428,35 +554,45 @@ static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return ret;
 }
 
-
 static int it913x_download_firmware(struct usb_device *udev,
                                        const struct firmware *fw)
 {
-       int ret = 0, i;
-       u8 packet_size, dlen;
+       int ret = 0, i = 0, pos = 0;
+       u8 packet_size, min_pkt;
        u8 *fw_data;
 
-       packet_size = 0x29;
-
        ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
 
        info("FRM Starting Firmware Download");
-       /* This uses scatter write firmware headers follow */
-       /* 03 XX 00     XX = chip number? */ 
-
-       for (i = 0; i < fw->size; i += packet_size) {
-                       if (i > 0)
-                               packet_size = 0x39;
-                       fw_data = (u8 *)(fw->data + i);
-                       dlen = ((i + packet_size) > fw->size)
-                               ? (fw->size - i) : packet_size;
-                       ret |= it913x_io(udev, WRITE_DATA, DEV_0,
-                               CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
-                       udelay(1000);
+
+       /* Multi firmware loader */
+       /* This uses scatter write firmware headers */
+       /* The firmware must start with 03 XX 00 */
+       /* and be the extact firmware length */
+
+       if (it913x_config.chip_ver == 2)
+               min_pkt = 0x11;
+       else
+               min_pkt = 0x19;
+
+       while (i <= fw->size) {
+               if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0))
+                       || (i == fw->size)) {
+                       packet_size = i - pos;
+                       if ((packet_size > min_pkt) || (i == fw->size)) {
+                               fw_data = (u8 *)(fw->data + pos);
+                               pos += packet_size;
+                               if (packet_size > 0)
+                                       ret |= it913x_io(udev, WRITE_DATA,
+                                               DEV_0, CMD_SCATTER_WRITE, 0,
+                                               0, fw_data, packet_size);
+                               udelay(1000);
+                       }
+               }
+               i++;
        }
 
-       ret |= it913x_io(udev, WRITE_CMD, DEV_0,
-                       CMD_BOOT, 0, 0, NULL, 0);
+       ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
 
        msleep(100);
 
@@ -474,12 +610,17 @@ static int it913x_download_firmware(struct usb_device *udev,
        /* Tuner function */
        if (it913x_config.dual_mode)
                ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
-
-       ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
-       ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
-       if (it913x_config.dual_mode) {
-               ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
-               ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
+       else
+               ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0x68);
+
+       if ((it913x_config.chip_ver == 1) &&
+               (it913x_config.chip_type == 0x9135)) {
+               ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
+               ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
+               if (it913x_config.dual_mode) {
+                       ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
+                       ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
+               }
        }
 
        return (ret < 0) ? -ENODEV : 0;
@@ -500,32 +641,23 @@ static int it913x_name(struct dvb_usb_adapter *adap)
 static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
 {
        struct usb_device *udev = adap->dev->udev;
+       struct it913x_state *st = adap->dev->priv;
        int ret = 0;
-       u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
        u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
-       u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
-       u8 tuner_id, tuner_type;
+       u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize / 4;
+       u8 pkt_size = 0x80;
+
+       if (adap->dev->udev->speed != USB_SPEED_HIGH)
+               pkt_size = 0x10;
+
+       it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
 
        if (adap->id == 0)
-               tuner_id = it913x_config.tuner_id_0;
-       else
-               tuner_id = it913x_config.tuner_id_1;
-
-       /* TODO we always use IT9137 possible references here*/
-       /* Documentation suggests don't care */
-       switch (tuner_id) {
-       case 0x51:
-       case 0x52:
-       case 0x60:
-       case 0x61:
-       case 0x62:
-       default:
-       case 0x38:
-               tuner_type = IT9137;
-       }
+               memcpy(&st->it913x_config, &it913x_config,
+                       sizeof(struct ite_config));
 
        adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
-               &adap->dev->i2c_adap, adap_addr, adf, tuner_type);
+               &adap->dev->i2c_adap, adap_addr, &st->it913x_config);
 
        if (adap->id == 0 && adap->fe_adap[0].fe) {
                ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
@@ -536,13 +668,13 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
                ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
                                        ep_size & 0xff);
                ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
-               ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80);
+               ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, pkt_size);
        } else if (adap->id == 1 && adap->fe_adap[0].fe) {
                ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
                ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
                                        ep_size & 0xff);
                ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
-               ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80);
+               ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, pkt_size);
                ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
                ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
                ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
@@ -582,6 +714,9 @@ static int it913x_probe(struct usb_interface *intf,
 static struct usb_device_id it913x_table[] = {
        { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
        { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
+       { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137) },
+       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005) },
+       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006) },
        {}              /* Terminating entry */
 };
 
@@ -614,8 +749,8 @@ static struct dvb_usb_device_properties it913x_properties = {
                                .endpoint = 0x04,
                                .u = {/* Keep Low if PID filter on */
                                        .bulk = {
-                                               .buffersize = 3584,
-
+                                       .buffersize =
+                                               TS_BUFFER_SIZE_PID,
                                        }
                                }
                        }
@@ -639,8 +774,8 @@ static struct dvb_usb_device_properties it913x_properties = {
                                .endpoint = 0x05,
                                .u = {
                                        .bulk = {
-                                               .buffersize = 3584,
-
+                                               .buffersize =
+                                                       TS_BUFFER_SIZE_PID,
                                        }
                                }
                        }
@@ -654,10 +789,10 @@ static struct dvb_usb_device_properties it913x_properties = {
                .rc_query       = it913x_rc_query,
                .rc_interval    = IT913X_POLL,
                .allowed_protos = RC_TYPE_NEC,
-               .rc_codes       = RC_MAP_KWORLD_315U,
+               .rc_codes       = RC_MAP_MSI_DIGIVOX_III,
        },
        .i2c_algo         = &it913x_i2c_algo,
-       .num_device_descs = 2,
+       .num_device_descs = 5,
        .devices = {
                {   "Kworld UB499-2T T09(IT9137)",
                        { &it913x_table[0], NULL },
@@ -665,6 +800,15 @@ static struct dvb_usb_device_properties it913x_properties = {
                {   "ITE 9135 Generic",
                        { &it913x_table[1], NULL },
                        },
+               {   "Sveon STV22 Dual DVB-T HDTV(IT9137)",
+                       { &it913x_table[2], NULL },
+                       },
+               {   "ITE 9135(9005) Generic",
+                       { &it913x_table[3], NULL },
+                       },
+               {   "ITE 9135(9006) Generic",
+                       { &it913x_table[4], NULL },
+                       },
        }
 };
 
@@ -679,5 +823,5 @@ module_usb_driver(it913x_driver);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.07");
+MODULE_VERSION("1.22");
 MODULE_LICENSE("GPL");
index 1a876a65ed56d6df38087cef69d7a5301fe2e325..b3fe05bbffc955bcbd45ea9830729f7bd22a6d53 100644 (file)
@@ -388,8 +388,7 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
        deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
                pid, index, onoff);
 
-       if (onoff)
-               if (!pid_filter) {
+       if (onoff) {
                        ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
                        if (ret < 0)
                                return -EAGAIN;
@@ -654,6 +653,9 @@ static int lme2510_identify_state(struct usb_device *udev,
                struct dvb_usb_device_description **desc,
                int *cold)
 {
+       if (pid_filter > 0)
+               props->adapter[0].fe[0].caps &=
+                       ~DVB_USB_ADAP_NEED_PID_FILTERING;
        *cold = 0;
        return 0;
 }
@@ -1293,5 +1295,5 @@ module_usb_driver(lme2510_driver);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.90");
+MODULE_VERSION("1.91");
 MODULE_LICENSE("GPL");
index d1f58371c7119209c24a74bafb54a328a530fdb7..d83df4bb72d352308f8baff11e7fe6ad72a63026 100644 (file)
@@ -102,8 +102,8 @@ fail:
 }
 
 static
-int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
-                                        fe_modulation_t *constellation)
+int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
+                                        fe_modulation_t *modulation)
 {
        u8 val;
        int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
@@ -113,13 +113,13 @@ int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
 
        switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
        case 0:
-               *constellation = QPSK;
+               *modulation = QPSK;
                break;
        case 1:
-               *constellation = QAM_16;
+               *modulation = QAM_16;
                break;
        case 2:
-               *constellation = QAM_64;
+               *modulation = QAM_64;
                break;
        }
 fail:
@@ -284,8 +284,7 @@ static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
 
 /* ------------------------------------------------------------------------ */
 
-static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
-                                      struct dvb_frontend_parameters *param)
+static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
 {
        struct mxl111sf_demod_state *state = fe->demodulator_priv;
        int ret = 0;
@@ -303,7 +302,7 @@ static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
        mxl_dbg("()");
 
        if (fe->ops.tuner_ops.set_params) {
-               ret = fe->ops.tuner_ops.set_params(fe, param);
+               ret = fe->ops.tuner_ops.set_params(fe);
                if (mxl_fail(ret))
                        goto fail;
                msleep(50);
@@ -481,13 +480,13 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
                                               u16 *signal_strength)
 {
        struct mxl111sf_demod_state *state = fe->demodulator_priv;
-       fe_modulation_t constellation;
+       fe_modulation_t modulation;
        u16 snr;
 
        mxl111sf_demod_calc_snr(state, &snr);
-       mxl1x1sf_demod_get_tps_constellation(state, &constellation);
+       mxl1x1sf_demod_get_tps_modulation(state, &modulation);
 
-       switch (constellation) {
+       switch (modulation) {
        case QPSK:
                *signal_strength = (snr >= 1300) ?
                        min(65535, snr * 44) : snr * 38;
@@ -508,9 +507,9 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
        return 0;
 }
 
-static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
-                                      struct dvb_frontend_parameters *p)
+static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mxl111sf_demod_state *state = fe->demodulator_priv;
 
        mxl_dbg("()");
@@ -518,18 +517,18 @@ static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
        p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
 #endif
        if (fe->ops.tuner_ops.get_bandwidth)
-               fe->ops.tuner_ops.get_bandwidth(fe, &p->u.ofdm.bandwidth);
+               fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
        if (fe->ops.tuner_ops.get_frequency)
                fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
-       mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_HP);
-       mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_LP);
-       mxl1x1sf_demod_get_tps_constellation(state, &p->u.ofdm.constellation);
+       mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
+       mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
+       mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
        mxl1x1sf_demod_get_tps_guard_fft_mode(state,
-                                             &p->u.ofdm.transmission_mode);
+                                             &p->transmission_mode);
        mxl1x1sf_demod_get_tps_guard_interval(state,
-                                             &p->u.ofdm.guard_interval);
+                                             &p->guard_interval);
        mxl1x1sf_demod_get_tps_hierarchy(state,
-                                        &p->u.ofdm.hierarchy_information);
+                                        &p->hierarchy);
 
        return 0;
 }
@@ -551,10 +550,9 @@ static void mxl111sf_demod_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops mxl111sf_demod_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name               = "MaxLinear MxL111SF DVB-T demodulator",
-               .type               = FE_OFDM,
                .frequency_min      = 177000000,
                .frequency_max      = 858000000,
                .frequency_stepsize = 166666,
index a6341058c4e71da379f0774bed2f2a985d31534f..72db6eef4b9c32f69140992216dd954b821c6e4c 100644 (file)
@@ -38,6 +38,8 @@ struct mxl111sf_tuner_state {
 
        struct mxl111sf_tuner_config *cfg;
 
+       enum mxl_if_freq if_freq;
+
        u32 frequency;
        u32 bandwidth;
 };
@@ -186,7 +188,10 @@ static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
        ctrl = iffcw & 0x00ff;
 #endif
        ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
-       mxl_fail(ret);
+       if (mxl_fail(ret))
+               goto fail;
+
+       state->if_freq = state->cfg->if_freq;
 fail:
        return ret;
 }
@@ -267,55 +272,49 @@ static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
 
 /* ------------------------------------------------------------------------ */
 
-static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
-                                    struct dvb_frontend_parameters *params)
+static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys  = c->delivery_system;
        struct mxl111sf_tuner_state *state = fe->tuner_priv;
        int ret;
        u8 bw;
 
        mxl_dbg("()");
 
-       if (fe->ops.info.type == FE_ATSC) {
-               switch (params->u.vsb.modulation) {
-               case VSB_8:
-               case VSB_16:
-                       bw = 0; /* ATSC */
-                       break;
-               case QAM_64:
-               case QAM_256:
-                       bw = 1; /* US CABLE */
-                       break;
-               default:
-                       err("%s: modulation not set!", __func__);
-                       return -EINVAL;
-               }
-       } else if (fe->ops.info.type == FE_OFDM) {
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
+       switch (delsys) {
+       case SYS_ATSC:
+               bw = 0; /* ATSC */
+               break;
+       case SYS_DVBC_ANNEX_B:
+               bw = 1; /* US CABLE */
+               break;
+       case SYS_DVBT:
+               switch (c->bandwidth_hz) {
+               case 6000000:
                        bw = 6;
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        bw = 7;
                        break;
-               case BANDWIDTH_8_MHZ:
+               case 8000000:
                        bw = 8;
                        break;
                default:
                        err("%s: bandwidth not set!", __func__);
                        return -EINVAL;
                }
-       } else {
+               break;
+       default:
                err("%s: modulation type not supported!", __func__);
                return -EINVAL;
        }
-       ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
+       ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
        if (mxl_fail(ret))
                goto fail;
 
-       state->frequency = params->frequency;
-       state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
-               params->u.ofdm.bandwidth : 0;
+       state->frequency = c->frequency;
+       state->bandwidth = c->bandwidth_hz;
 fail:
        return ret;
 }
@@ -407,6 +406,54 @@ static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
        return 0;
 }
 
+static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
+                                          u32 *frequency)
+{
+       struct mxl111sf_tuner_state *state = fe->tuner_priv;
+
+       *frequency = 0;
+
+       switch (state->if_freq) {
+       case MXL_IF_4_0:   /* 4.0   MHz */
+               *frequency = 4000000;
+               break;
+       case MXL_IF_4_5:   /* 4.5   MHz */
+               *frequency = 4500000;
+               break;
+       case MXL_IF_4_57:  /* 4.57  MHz */
+               *frequency = 4570000;
+               break;
+       case MXL_IF_5_0:   /* 5.0   MHz */
+               *frequency = 5000000;
+               break;
+       case MXL_IF_5_38:  /* 5.38  MHz */
+               *frequency = 5380000;
+               break;
+       case MXL_IF_6_0:   /* 6.0   MHz */
+               *frequency = 6000000;
+               break;
+       case MXL_IF_6_28:  /* 6.28  MHz */
+               *frequency = 6280000;
+               break;
+       case MXL_IF_7_2:   /* 7.2   MHz */
+               *frequency = 7200000;
+               break;
+       case MXL_IF_35_25: /* 35.25 MHz */
+               *frequency = 35250000;
+               break;
+       case MXL_IF_36:    /* 36    MHz */
+               *frequency = 36000000;
+               break;
+       case MXL_IF_36_15: /* 36.15 MHz */
+               *frequency = 36150000;
+               break;
+       case MXL_IF_44:    /* 44    MHz */
+               *frequency = 44000000;
+               break;
+       }
+       return 0;
+}
+
 static int mxl111sf_tuner_release(struct dvb_frontend *fe)
 {
        struct mxl111sf_tuner_state *state = fe->tuner_priv;
@@ -436,6 +483,7 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
        .get_rf_strength   = mxl111sf_get_rf_strength,
        .get_frequency     = mxl111sf_tuner_get_frequency,
        .get_bandwidth     = mxl111sf_tuner_get_bandwidth,
+       .get_if_frequency  = mxl111sf_tuner_get_if_frequency,
        .release           = mxl111sf_tuner_release,
 };
 
index 825a8b242e09b41ac6a62cc8881a80de9e6cead7..38ef0253d3b5b9c79aa1daade821f241f90e6800 100644 (file)
@@ -758,6 +758,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
 
 
 #define MXL111SF_EP4_BULK_STREAMING_CONFIG             \
+       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
        .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
        .stream = {                                     \
                .type = USB_BULK,                       \
@@ -772,6 +773,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
 
 /* FIXME: works for v6 but not v8 silicon */
 #define MXL111SF_EP4_ISOC_STREAMING_CONFIG             \
+       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
        .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
        .stream = {                                     \
                .type = USB_ISOC,                       \
@@ -788,6 +790,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
        }
 
 #define MXL111SF_EP6_BULK_STREAMING_CONFIG             \
+       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
        .streaming_ctrl = mxl111sf_ep6_streaming_ctrl,  \
        .stream = {                                     \
                .type = USB_BULK,                       \
@@ -802,6 +805,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
 
 /* FIXME */
 #define MXL111SF_EP6_ISOC_STREAMING_CONFIG             \
+       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
        .streaming_ctrl = mxl111sf_ep6_streaming_ctrl,  \
        .stream = {                                     \
                .type = USB_ISOC,                       \
@@ -839,8 +843,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
                .fe_ioctl_override = mxl111sf_fe_ioctl_override,
                .num_frontends = 1,
                .fe = {{
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_attach_demod,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
@@ -883,8 +885,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
                .fe_ioctl_override = mxl111sf_fe_ioctl_override,
                .num_frontends = 1,
                .fe = {{
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_attach_demod,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
@@ -927,16 +927,12 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
                .fe_ioctl_override = mxl111sf_fe_ioctl_override,
                .num_frontends = 2,
                .fe = {{
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
                        MXL111SF_EP6_BULK_STREAMING_CONFIG,
                },
                {
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_attach_demod,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
@@ -992,16 +988,12 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
                .fe_ioctl_override = mxl111sf_fe_ioctl_override,
                .num_frontends = 2,
                .fe = {{
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
                        MXL111SF_EP6_ISOC_STREAMING_CONFIG,
                },
                {
-                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
-
                        .frontend_attach  = mxl111sf_attach_demod,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
index 56acf8e55d506fd05517d4586f847e31b0b92974..e53a1061cb8e4451eeda3251376c9c0461106761 100644 (file)
@@ -75,10 +75,18 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
                u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
        struct ttusb2_state *st = d->priv;
-       u8 s[wlen+4],r[64] = { 0 };
+       u8 *s, *r = NULL;
        int ret = 0;
 
-       memset(s,0,wlen+4);
+       s = kzalloc(wlen+4, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+
+       r = kzalloc(64, GFP_KERNEL);
+       if (!r) {
+               kfree(s);
+               return -ENOMEM;
+       }
 
        s[0] = 0xaa;
        s[1] = ++st->id;
@@ -94,12 +102,17 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
                r[2] != cmd ||
                (rlen > 0 && r[3] != rlen)) {
                warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
+               kfree(s);
+               kfree(r);
                return -EIO;
        }
 
        if (rlen > 0)
                memcpy(rbuf, &r[4], rlen);
 
+       kfree(s);
+       kfree(r);
+
        return 0;
 }
 
@@ -384,7 +397,7 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
 
                memcpy(&obuf[3], msg[i].buf, msg[i].len);
 
-               if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
+               if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
                        err("i2c transfer failed.");
                        break;
                }
index 2bb8d4cc8d881765d76faa6b7fc7533672d80dde..5eab468dd9046adbe76738c157c60efd1bd66b76 100644 (file)
@@ -135,9 +135,9 @@ static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
        return 0;
 }
 
-static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int vp702x_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct vp702x_fe_state *st = fe->demodulator_priv;
        struct vp702x_device_state *dst = st->d->priv;
        u32 freq = fep->frequency/1000;
@@ -155,14 +155,14 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
        cmd[1] =  freq       & 0xff;
        cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
 
-       sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
+       sr = (u64) (fep->symbol_rate/1000) << 20;
        do_div(sr,88000);
        cmd[3] = (sr >> 12) & 0xff;
        cmd[4] = (sr >> 4)  & 0xff;
        cmd[5] = (sr << 4)  & 0xf0;
 
        deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
-                       fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
+                       fep->frequency, freq, freq, fep->symbol_rate,
                        (unsigned long) sr, (unsigned long) sr);
 
 /*     if (fep->inversion == INVERSION_ON)
@@ -171,7 +171,7 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
        if (st->voltage == SEC_VOLTAGE_18)
                cmd[6] |= 0x40;
 
-/*     if (fep->u.qpsk.symbol_rate > 8000000)
+/*     if (fep->symbol_rate > 8000000)
                cmd[6] |= 0x20;
 
        if (fep->frequency < 1531000)
@@ -211,13 +211,6 @@ static int vp702x_fe_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
-{
-       deb_fe("%s\n",__func__);
-       return 0;
-}
-
 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
                                    struct dvb_diseqc_master_cmd *m)
 {
@@ -350,9 +343,9 @@ error:
 
 
 static struct dvb_frontend_ops vp702x_fe_ops = {
+       .delsys = { SYS_DVBS },
        .info = {
                .name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
-               .type           = FE_QPSK,
                .frequency_min       = 950000,
                .frequency_max       = 2150000,
                .frequency_stepsize  = 1000,   /* kHz for QPSK frontends */
@@ -371,7 +364,6 @@ static struct dvb_frontend_ops vp702x_fe_ops = {
        .sleep = vp702x_fe_sleep,
 
        .set_frontend = vp702x_fe_set_frontend,
-       .get_frontend = vp702x_fe_get_frontend,
        .get_tune_settings = vp702x_fe_get_tune_settings,
 
        .read_status = vp702x_fe_read_status,
index 8452eef90322be8d97e9a08c81881cc47f6cf311..b8825b18c003a32c52066f616b26ef0b95758f21 100644 (file)
@@ -103,9 +103,9 @@ static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
        return 0;
 }
 
-static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int vp7045_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct vp7045_fe_state *state = fe->demodulator_priv;
        u8 buf[5];
        u32 freq = fep->frequency / 1000;
@@ -115,25 +115,24 @@ static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
        buf[2] =  freq        & 0xff;
        buf[3] = 0;
 
-       switch (fep->u.ofdm.bandwidth) {
-               case BANDWIDTH_8_MHZ: buf[4] = 8; break;
-               case BANDWIDTH_7_MHZ: buf[4] = 7; break;
-               case BANDWIDTH_6_MHZ: buf[4] = 6; break;
-               case BANDWIDTH_AUTO: return -EOPNOTSUPP;
-               default:
-                       return -EINVAL;
+       switch (fep->bandwidth_hz) {
+       case 8000000:
+               buf[4] = 8;
+               break;
+       case 7000000:
+               buf[4] = 7;
+               break;
+       case 6000000:
+               buf[4] = 6;
+               break;
+       default:
+               return -EINVAL;
        }
 
        vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
        return 0;
 }
 
-static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
-{
-       return 0;
-}
-
 static void vp7045_fe_release(struct dvb_frontend* fe)
 {
        struct vp7045_fe_state *state = fe->demodulator_priv;
@@ -159,9 +158,9 @@ error:
 
 
 static struct dvb_frontend_ops vp7045_fe_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Twinhan VP7045/46 USB DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 44250000,
                .frequency_max          = 867250000,
                .frequency_stepsize     = 1000,
@@ -181,7 +180,6 @@ static struct dvb_frontend_ops vp7045_fe_ops = {
        .sleep = vp7045_fe_sleep,
 
        .set_frontend = vp7045_fe_set_frontend,
-       .get_frontend = vp7045_fe_get_frontend,
        .get_tune_settings = vp7045_fe_get_tune_settings,
 
        .read_status = vp7045_fe_read_status,
index 489ae8245867bc51d83cfa062c71fc09952531b9..d1a1a1324ef87018e030ba0aa149de3c79856085 100644 (file)
@@ -335,7 +335,7 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
  * (not supported by the AVC standard)
  */
 static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
-                             struct dvb_frontend_parameters *params)
+                             struct dtv_frontend_properties *p)
 {
        struct avc_command_frame *c = (void *)fdtv->avc_data;
 
@@ -349,15 +349,15 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
        else
                c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
 
-       c->operand[4] = (params->frequency >> 24) & 0xff;
-       c->operand[5] = (params->frequency >> 16) & 0xff;
-       c->operand[6] = (params->frequency >> 8) & 0xff;
-       c->operand[7] = params->frequency & 0xff;
+       c->operand[4] = (p->frequency >> 24) & 0xff;
+       c->operand[5] = (p->frequency >> 16) & 0xff;
+       c->operand[6] = (p->frequency >> 8) & 0xff;
+       c->operand[7] = p->frequency & 0xff;
 
-       c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
-       c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
+       c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
+       c->operand[9] = (p->symbol_rate / 1000) & 0xff;
 
-       switch (params->u.qpsk.fec_inner) {
+       switch (p->fec_inner) {
        case FEC_1_2:   c->operand[10] = 0x1; break;
        case FEC_2_3:   c->operand[10] = 0x2; break;
        case FEC_3_4:   c->operand[10] = 0x3; break;
@@ -392,10 +392,11 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
                        default:                c->operand[13] = 0x2; break;
                        }
                        switch (fdtv->fe.dtv_property_cache.rolloff) {
-                       case ROLLOFF_AUTO:      c->operand[14] = 0x2; break;
                        case ROLLOFF_35:        c->operand[14] = 0x2; break;
                        case ROLLOFF_20:        c->operand[14] = 0x0; break;
                        case ROLLOFF_25:        c->operand[14] = 0x1; break;
+                       case ROLLOFF_AUTO:
+                       default:                c->operand[14] = 0x2; break;
                        /* case ROLLOFF_NONE:   c->operand[14] = 0xff; break; */
                        }
                        switch (fdtv->fe.dtv_property_cache.pilot) {
@@ -415,7 +416,7 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
 }
 
 static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
-                              struct dvb_frontend_parameters *params)
+                              struct dtv_frontend_properties *p)
 {
        struct avc_command_frame *c = (void *)fdtv->avc_data;
 
@@ -434,8 +435,8 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
                        | 1 << 4 /* Frequency */
                        | 1 << 3 /* Symbol_Rate */
                        | 0 << 2 /* FEC_outer */
-                       | (params->u.qam.fec_inner  != FEC_AUTO ? 1 << 1 : 0)
-                       | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
+                       | (p->fec_inner  != FEC_AUTO ? 1 << 1 : 0)
+                       | (p->modulation != QAM_AUTO ? 1 << 0 : 0);
 
        /* multiplex_valid_flags, low byte */
        c->operand[6] =   0 << 7 /* NetworkID */
@@ -446,15 +447,15 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
        c->operand[9]  = 0x00;
        c->operand[10] = 0x00;
 
-       c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
-       c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
-       c->operand[13] = (params->frequency / 4000) & 0xff;
-       c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
-       c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
-       c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
+       c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+       c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
+       c->operand[13] = (p->frequency / 4000) & 0xff;
+       c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
+       c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
+       c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
        c->operand[17] = 0x00;
 
-       switch (params->u.qpsk.fec_inner) {
+       switch (p->fec_inner) {
        case FEC_1_2:   c->operand[18] = 0x1; break;
        case FEC_2_3:   c->operand[18] = 0x2; break;
        case FEC_3_4:   c->operand[18] = 0x3; break;
@@ -466,7 +467,7 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
        default:        c->operand[18] = 0x0;
        }
 
-       switch (params->u.qam.modulation) {
+       switch (p->modulation) {
        case QAM_16:    c->operand[19] = 0x08; break;
        case QAM_32:    c->operand[19] = 0x10; break;
        case QAM_64:    c->operand[19] = 0x18; break;
@@ -483,9 +484,8 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
 }
 
 static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
-                              struct dvb_frontend_parameters *params)
+                              struct dtv_frontend_properties *p)
 {
-       struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
        struct avc_command_frame *c = (void *)fdtv->avc_data;
 
        c->opcode = AVC_OPCODE_DSD;
@@ -500,42 +500,42 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
        c->operand[5] =
              0 << 7 /* reserved */
            | 1 << 6 /* CenterFrequency */
-           | (ofdm->bandwidth      != BANDWIDTH_AUTO        ? 1 << 5 : 0)
-           | (ofdm->constellation  != QAM_AUTO              ? 1 << 4 : 0)
-           | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
-           | (ofdm->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
-           | (ofdm->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
-           | (ofdm->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
+           | (p->bandwidth_hz != 0        ? 1 << 5 : 0)
+           | (p->modulation  != QAM_AUTO              ? 1 << 4 : 0)
+           | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
+           | (p->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
+           | (p->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
+           | (p->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
 
        /* multiplex_valid_flags, low byte */
        c->operand[6] =
              0 << 7 /* NetworkID */
-           | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+           | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
            | 0 << 5 /* OtherFrequencyFlag */
            | 0 << 0 /* reserved */ ;
 
        c->operand[7]  = 0x0;
-       c->operand[8]  = (params->frequency / 10) >> 24;
-       c->operand[9]  = ((params->frequency / 10) >> 16) & 0xff;
-       c->operand[10] = ((params->frequency / 10) >>  8) & 0xff;
-       c->operand[11] = (params->frequency / 10) & 0xff;
-
-       switch (ofdm->bandwidth) {
-       case BANDWIDTH_7_MHZ:   c->operand[12] = 0x20; break;
-       case BANDWIDTH_8_MHZ:
-       case BANDWIDTH_6_MHZ:   /* not defined by AVC spec */
-       case BANDWIDTH_AUTO:
+       c->operand[8]  = (p->frequency / 10) >> 24;
+       c->operand[9]  = ((p->frequency / 10) >> 16) & 0xff;
+       c->operand[10] = ((p->frequency / 10) >>  8) & 0xff;
+       c->operand[11] = (p->frequency / 10) & 0xff;
+
+       switch (p->bandwidth_hz) {
+       case 7000000:   c->operand[12] = 0x20; break;
+       case 8000000:
+       case 6000000:   /* not defined by AVC spec */
+       case 0:
        default:                c->operand[12] = 0x00;
        }
 
-       switch (ofdm->constellation) {
+       switch (p->modulation) {
        case QAM_16:    c->operand[13] = 1 << 6; break;
        case QAM_64:    c->operand[13] = 2 << 6; break;
        case QPSK:
        default:        c->operand[13] = 0x00;
        }
 
-       switch (ofdm->hierarchy_information) {
+       switch (p->hierarchy) {
        case HIERARCHY_1:       c->operand[13] |= 1 << 3; break;
        case HIERARCHY_2:       c->operand[13] |= 2 << 3; break;
        case HIERARCHY_4:       c->operand[13] |= 3 << 3; break;
@@ -544,7 +544,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
        default:                break;
        }
 
-       switch (ofdm->code_rate_HP) {
+       switch (p->code_rate_HP) {
        case FEC_2_3:   c->operand[13] |= 1; break;
        case FEC_3_4:   c->operand[13] |= 2; break;
        case FEC_5_6:   c->operand[13] |= 3; break;
@@ -553,7 +553,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
        default:        break;
        }
 
-       switch (ofdm->code_rate_LP) {
+       switch (p->code_rate_LP) {
        case FEC_2_3:   c->operand[14] = 1 << 5; break;
        case FEC_3_4:   c->operand[14] = 2 << 5; break;
        case FEC_5_6:   c->operand[14] = 3 << 5; break;
@@ -562,7 +562,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
        default:        c->operand[14] = 0x00; break;
        }
 
-       switch (ofdm->guard_interval) {
+       switch (p->guard_interval) {
        case GUARD_INTERVAL_1_16:       c->operand[14] |= 1 << 3; break;
        case GUARD_INTERVAL_1_8:        c->operand[14] |= 2 << 3; break;
        case GUARD_INTERVAL_1_4:        c->operand[14] |= 3 << 3; break;
@@ -571,7 +571,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
        default:                        break;
        }
 
-       switch (ofdm->transmission_mode) {
+       switch (p->transmission_mode) {
        case TRANSMISSION_MODE_8K:      c->operand[14] |= 1 << 1; break;
        case TRANSMISSION_MODE_2K:
        case TRANSMISSION_MODE_AUTO:
@@ -585,7 +585,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
 }
 
 int avc_tuner_dsd(struct firedtv *fdtv,
-                 struct dvb_frontend_parameters *params)
+                 struct dtv_frontend_properties *p)
 {
        struct avc_command_frame *c = (void *)fdtv->avc_data;
        int pos, ret;
@@ -597,9 +597,9 @@ int avc_tuner_dsd(struct firedtv *fdtv,
 
        switch (fdtv->type) {
        case FIREDTV_DVB_S:
-       case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
-       case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
-       case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
+       case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
+       case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
+       case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
        default:
                BUG();
        }
index fd8bbbfa5c598e39896aaae1ea5e001002bdb6d5..eb7496eab130cfb54d5daa39717e61ed3594a695 100644 (file)
@@ -203,7 +203,9 @@ int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
        if (err)
                goto fail_rem_frontend;
 
-       dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+       err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+       if (err)
+               goto fail_disconnect_frontend;
 
        fdtv_frontend_init(fdtv, name);
        err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
@@ -218,6 +220,7 @@ int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
 
 fail_net_release:
        dvb_net_release(&fdtv->dvbnet);
+fail_disconnect_frontend:
        fdtv->demux.dmx.close(&fdtv->demux.dmx);
 fail_rem_frontend:
        fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
index 8748a61be73d2d8e32d0b65fd95396c2c4269b5b..6fe9793b98b3cfe19dfc22f664c3696ad78d71f3 100644 (file)
@@ -141,28 +141,12 @@ static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
        return -EOPNOTSUPP;
 }
 
-static int fdtv_set_frontend(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *params)
+static int fdtv_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct firedtv *fdtv = fe->sec_priv;
 
-       return avc_tuner_dsd(fdtv, params);
-}
-
-static int fdtv_get_frontend(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *params)
-{
-       return -EOPNOTSUPP;
-}
-
-static int fdtv_get_property(struct dvb_frontend *fe, struct dtv_property *tvp)
-{
-       return 0;
-}
-
-static int fdtv_set_property(struct dvb_frontend *fe, struct dtv_property *tvp)
-{
-       return 0;
+       return avc_tuner_dsd(fdtv, p);
 }
 
 void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
@@ -174,10 +158,6 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
        ops->sleep                      = fdtv_sleep;
 
        ops->set_frontend               = fdtv_set_frontend;
-       ops->get_frontend               = fdtv_get_frontend;
-
-       ops->get_property               = fdtv_get_property;
-       ops->set_property               = fdtv_set_property;
 
        ops->read_status                = fdtv_read_status;
        ops->read_ber                   = fdtv_read_ber;
@@ -192,7 +172,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
 
        switch (fdtv->type) {
        case FIREDTV_DVB_S:
-               fi->type                = FE_QPSK;
+               ops->delsys[0]          = SYS_DVBS;
 
                fi->frequency_min       = 950000;
                fi->frequency_max       = 2150000;
@@ -211,7 +191,8 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
                break;
 
        case FIREDTV_DVB_S2:
-               fi->type                = FE_QPSK;
+               ops->delsys[0]          = SYS_DVBS;
+               ops->delsys[1]          = SYS_DVBS2;
 
                fi->frequency_min       = 950000;
                fi->frequency_max       = 2150000;
@@ -231,7 +212,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
                break;
 
        case FIREDTV_DVB_C:
-               fi->type                = FE_QAM;
+               ops->delsys[0]          = SYS_DVBC_ANNEX_A;
 
                fi->frequency_min       = 47000000;
                fi->frequency_max       = 866000000;
@@ -249,7 +230,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
                break;
 
        case FIREDTV_DVB_T:
-               fi->type                = FE_OFDM;
+               ops->delsys[0]          = SYS_DVBT;
 
                fi->frequency_min       = 49000000;
                fi->frequency_max       = 861000000;
index bd00b04e079ddd0b7f667b9581118b47633cc2f5..4fdcd8cb753010416bbbf1d7c271208541b4b157 100644 (file)
@@ -112,8 +112,8 @@ struct firedtv {
 /* firedtv-avc.c */
 int avc_recv(struct firedtv *fdtv, void *data, size_t length);
 int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
-struct dvb_frontend_parameters;
-int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
+struct dtv_frontend_properties;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dtv_frontend_properties *params);
 int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
 int avc_tuner_get_ts(struct firedtv *fdtv);
 int avc_identify_subunit(struct firedtv *fdtv);
index 4a2d2e6c91ab9f78f17715234cc4961a3397becd..ebb5ed7a7783ee7da77a3a87fa7e406db9a0bb61 100644 (file)
@@ -404,6 +404,13 @@ config DVB_EC100
        help
          Say Y when you want to support this frontend.
 
+config DVB_HD29L2
+       tristate "HDIC HD29L2"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         Say Y when you want to support this frontend.
+
 config DVB_STV0367
        tristate "ST STV0367 based"
        depends on DVB_CORE && I2C
index f639f67815515d40c8ff51b3a41a2ec52c456760..00a20636df62aad0944fc431c4cfdf026c7a7128 100644 (file)
@@ -84,6 +84,7 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o
 obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
 obj-$(CONFIG_DVB_ISL6423) += isl6423.o
 obj-$(CONFIG_DVB_EC100) += ec100.o
+obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
 obj-$(CONFIG_DVB_DS3000) += ds3000.o
 obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
 obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
index 345311c333838ace3ee21fd751051a74cb472270..6bcbcf543b38ea6be973e98b52d0247af8ab96b0 100644 (file)
@@ -2,6 +2,7 @@
  * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
  *
  * Thanks to Afatech who kindly provided information.
  *
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
 #include "af9013_priv.h"
-#include "af9013.h"
 
 int af9013_debug;
+module_param_named(debug, af9013_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
 struct af9013_state {
        struct i2c_adapter *i2c;
-       struct dvb_frontend frontend;
-
+       struct dvb_frontend fe;
        struct af9013_config config;
 
        /* tuner/demod RF and IF AGC limits used for signal strength calc */
@@ -48,107 +39,178 @@ struct af9013_state {
        u32 ber;
        u32 ucblocks;
        u16 snr;
-       u32 frequency;
-       unsigned long next_statistics_check;
+       u32 bandwidth_hz;
+       fe_status_t fe_status;
+       unsigned long set_frontend_jiffies;
+       unsigned long read_status_jiffies;
+       bool first_tune;
+       bool i2c_gate_state;
+       unsigned int statistics_step:3;
+       struct delayed_work statistics_work;
 };
 
-static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
-
-static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg,
-       u8 *val, u8 len)
+/* write multiple registers */
+static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+       const u8 *val, int len)
 {
+       int ret;
        u8 buf[3+len];
-       struct i2c_msg msg = {
-               .addr = state->config.demod_address,
-               .flags = 0,
-               .len = sizeof(buf),
-               .buf = buf };
-
-       buf[0] = reg >> 8;
-       buf[1] = reg & 0xff;
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = priv->config.i2c_addr,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = (reg >> 8) & 0xff;
+       buf[1] = (reg >> 0) & 0xff;
        buf[2] = mbox;
        memcpy(&buf[3], val, len);
 
-       if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-               warn("I2C write failed reg:%04x len:%d", reg, len);
-               return -EREMOTEIO;
+       ret = i2c_transfer(priv->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len);
+               ret = -EREMOTEIO;
        }
-       return 0;
+       return ret;
 }
 
-static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val,
-       u8 len)
+/* read multiple registers */
+static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+       u8 *val, int len)
 {
-       u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7);
-       return af9013_write_regs(state, mbox, reg, val, len);
+       int ret;
+       u8 buf[3];
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = priv->config.i2c_addr,
+                       .flags = 0,
+                       .len = 3,
+                       .buf = buf,
+               }, {
+                       .addr = priv->config.i2c_addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = val,
+               }
+       };
+
+       buf[0] = (reg >> 8) & 0xff;
+       buf[1] = (reg >> 0) & 0xff;
+       buf[2] = mbox;
+
+       ret = i2c_transfer(priv->i2c, msg, 2);
+       if (ret == 2) {
+               ret = 0;
+       } else {
+               warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+       return ret;
 }
 
-static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
-       u8 len)
+/* write multiple registers */
+static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const u8 *val,
+       int len)
 {
-       u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7);
-       return af9013_write_regs(state, mbox, reg, val, len);
+       int ret, i;
+       u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
+
+       if ((priv->config.ts_mode == AF9013_TS_USB) &&
+               ((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+               mbox |= ((len - 1) << 2);
+               ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
+       } else {
+               for (i = 0; i < len; i++) {
+                       ret = af9013_wr_regs_i2c(priv, mbox, reg+i, val+i, 1);
+                       if (ret)
+                               goto err;
+               }
+       }
+
+err:
+       return 0;
+}
+
+/* read multiple registers */
+static int af9013_rd_regs(struct af9013_state *priv, u16 reg, u8 *val, int len)
+{
+       int ret, i;
+       u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
+
+       if ((priv->config.ts_mode == AF9013_TS_USB) &&
+               ((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+               mbox |= ((len - 1) << 2);
+               ret = af9013_rd_regs_i2c(priv, mbox, reg, val, len);
+       } else {
+               for (i = 0; i < len; i++) {
+                       ret = af9013_rd_regs_i2c(priv, mbox, reg+i, val+i, 1);
+                       if (ret)
+                               goto err;
+               }
+       }
+
+err:
+       return 0;
 }
 
 /* write single register */
-static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val)
+static int af9013_wr_reg(struct af9013_state *priv, u16 reg, u8 val)
 {
-       return af9013_write_ofdm_regs(state, reg, &val, 1);
+       return af9013_wr_regs(priv, reg, &val, 1);
 }
 
 /* read single register */
-static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val)
+static int af9013_rd_reg(struct af9013_state *priv, u16 reg, u8 *val)
 {
-       u8 obuf[3] = { reg >> 8, reg & 0xff, 0 };
-       u8 ibuf[1];
-       struct i2c_msg msg[2] = {
-               {
-                       .addr = state->config.demod_address,
-                       .flags = 0,
-                       .len = sizeof(obuf),
-                       .buf = obuf
-               }, {
-                       .addr = state->config.demod_address,
-                       .flags = I2C_M_RD,
-                       .len = sizeof(ibuf),
-                       .buf = ibuf
-               }
-       };
+       return af9013_rd_regs(priv, reg, val, 1);
+}
 
-       if (i2c_transfer(state->i2c, msg, 2) != 2) {
-               warn("I2C read failed reg:%04x", reg);
-               return -EREMOTEIO;
-       }
-       *val = ibuf[0];
-       return 0;
+static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
+       u8 len)
+{
+       u8 mbox = (1 << 7)|(1 << 6)|((len - 1) << 2)|(1 << 1)|(1 << 0);
+       return af9013_wr_regs_i2c(state, mbox, reg, val, len);
 }
 
-static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
-       u8 len, u8 val)
+static int af9013_wr_reg_bits(struct af9013_state *state, u16 reg, int pos,
+       int len, u8 val)
 {
        int ret;
        u8 tmp, mask;
 
-       ret = af9013_read_reg(state, reg, &tmp);
-       if (ret)
-               return ret;
+       /* no need for read if whole reg is written */
+       if (len != 8) {
+               ret = af9013_rd_reg(state, reg, &tmp);
+               if (ret)
+                       return ret;
 
-       mask = regmask[len - 1] << pos;
-       tmp = (tmp & ~mask) | ((val << pos) & mask);
+               mask = (0xff >> (8 - len)) << pos;
+               val <<= pos;
+               tmp &= ~mask;
+               val |= tmp;
+       }
 
-       return af9013_write_reg(state, reg, tmp);
+       return af9013_wr_reg(state, reg, val);
 }
 
-static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
-       u8 len, u8 *val)
+static int af9013_rd_reg_bits(struct af9013_state *state, u16 reg, int pos,
+       int len, u8 *val)
 {
        int ret;
        u8 tmp;
 
-       ret = af9013_read_reg(state, reg, &tmp);
+       ret = af9013_rd_reg(state, reg, &tmp);
        if (ret)
                return ret;
-       *val = (tmp >> pos) & regmask[len - 1];
+
+       *val = (tmp >> pos);
+       *val &= (0xff >> (8 - len));
+
        return 0;
 }
 
@@ -157,10 +219,13 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
        int ret;
        u8 pos;
        u16 addr;
-       deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval);
 
-/* GPIO0 & GPIO1 0xd735
-   GPIO2 & GPIO3 0xd736 */
+       dbg("%s: gpio=%d gpioval=%02x", __func__, gpio, gpioval);
+
+       /*
+        * GPIO0 & GPIO1 0xd735
+        * GPIO2 & GPIO3 0xd736
+        */
 
        switch (gpio) {
        case 0:
@@ -175,7 +240,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
        default:
                err("invalid gpio:%d\n", gpio);
                ret = -EINVAL;
-               goto error;
+               goto err;
        };
 
        switch (gpio) {
@@ -190,16 +255,21 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
                break;
        };
 
-       ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval);
+       ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
+       if (ret)
+               goto err;
 
-error:
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
 static u32 af913_div(u32 a, u32 b, u32 x)
 {
        u32 r = 0, c = 0, i;
-       deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x);
+
+       dbg("%s: a=%d b=%d x=%d", __func__, a, b, x);
 
        if (a > b) {
                c = a / b;
@@ -216,205 +286,407 @@ static u32 af913_div(u32 a, u32 b, u32 x)
        }
        r = (c << (u32)x) + r;
 
-       deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r);
+       dbg("%s: a=%d b=%d x=%d r=%x", __func__, a, b, x, r);
        return r;
 }
 
-static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw)
+static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
 {
-       int ret, i, j, found;
-       deb_info("%s: adc_clock:%d bw:%d\n", __func__,
-               state->config.adc_clock, bw);
-
-       /* lookup coeff from table */
-       for (i = 0, found = 0; i < ARRAY_SIZE(coeff_table); i++) {
-               if (coeff_table[i].adc_clock == state->config.adc_clock &&
-                       coeff_table[i].bw == bw) {
-                       found = 1;
-                       break;
-               }
-       }
+       int ret, i;
+       u8 tmp;
 
-       if (!found) {
-               err("invalid bw or clock");
-               ret = -EINVAL;
-               goto error;
+       dbg("%s: onoff=%d", __func__, onoff);
+
+       /* enable reset */
+       ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1);
+       if (ret)
+               goto err;
+
+       /* start reset mechanism */
+       ret = af9013_wr_reg(state, 0xaeff, 1);
+       if (ret)
+               goto err;
+
+       /* wait reset performs */
+       for (i = 0; i < 150; i++) {
+               ret = af9013_rd_reg_bits(state, 0xd417, 1, 1, &tmp);
+               if (ret)
+                       goto err;
+
+               if (tmp)
+                       break; /* reset done */
+
+               usleep_range(5000, 25000);
        }
 
-       deb_info("%s: coeff: ", __func__);
-       debug_dump(coeff_table[i].val, sizeof(coeff_table[i].val), deb_info);
+       if (!tmp)
+               return -ETIMEDOUT;
 
-       /* program */
-       for (j = 0; j < sizeof(coeff_table[i].val); j++) {
-               ret = af9013_write_reg(state, 0xae00 + j,
-                       coeff_table[i].val[j]);
+       if (onoff) {
+               /* clear reset */
+               ret = af9013_wr_reg_bits(state, 0xd417, 1, 1, 0);
                if (ret)
-                       break;
+                       goto err;
+
+               /* disable reset */
+               ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 0);
+
+               /* power on */
+               ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 0);
+       } else {
+               /* power off */
+               ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 1);
        }
 
-error:
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
-static int af9013_set_adc_ctrl(struct af9013_state *state)
+static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
 {
+       struct af9013_state *state = fe->demodulator_priv;
        int ret;
-       u8 buf[3], tmp, i;
-       u32 adc_cw;
 
-       deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock);
+       dbg("%s", __func__);
 
-       /* adc frequency type */
-       switch (state->config.adc_clock) {
-       case 28800: /* 28.800 MHz */
-               tmp = 0;
-               break;
-       case 20480: /* 20.480 MHz */
-               tmp = 1;
+       /* reset and start BER counter */
+       ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1);
+       if (ret)
+               goto err;
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 buf[5];
+
+       dbg("%s", __func__);
+
+       /* check if error bit count is ready */
+       ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]);
+       if (ret)
+               goto err;
+
+       if (!buf[0]) {
+               dbg("%s: not ready", __func__);
+               return 0;
+       }
+
+       ret = af9013_rd_regs(state, 0xd387, buf, 5);
+       if (ret)
+               goto err;
+
+       state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+       state->ucblocks += (buf[4] << 8) | buf[3];
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_statistics_snr_start(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+
+       dbg("%s", __func__);
+
+       /* start SNR meas */
+       ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1);
+       if (ret)
+               goto err;
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_statistics_snr_result(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret, i, len;
+       u8 buf[3], tmp;
+       u32 snr_val;
+       const struct af9013_snr *uninitialized_var(snr_lut);
+
+       dbg("%s", __func__);
+
+       /* check if SNR ready */
+       ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp);
+       if (ret)
+               goto err;
+
+       if (!tmp) {
+               dbg("%s: not ready", __func__);
+               return 0;
+       }
+
+       /* read value */
+       ret = af9013_rd_regs(state, 0xd2e3, buf, 3);
+       if (ret)
+               goto err;
+
+       snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+       /* read current modulation */
+       ret = af9013_rd_reg(state, 0xd3c1, &tmp);
+       if (ret)
+               goto err;
+
+       switch ((tmp >> 6) & 3) {
+       case 0:
+               len = ARRAY_SIZE(qpsk_snr_lut);
+               snr_lut = qpsk_snr_lut;
                break;
-       case 28000: /* 28.000 MHz */
-               tmp = 2;
+       case 1:
+               len = ARRAY_SIZE(qam16_snr_lut);
+               snr_lut = qam16_snr_lut;
                break;
-       case 25000: /* 25.000 MHz */
-               tmp = 3;
+       case 2:
+               len = ARRAY_SIZE(qam64_snr_lut);
+               snr_lut = qam64_snr_lut;
                break;
        default:
-               err("invalid xtal");
-               return -EINVAL;
+               goto err;
+               break;
        }
 
-       adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul);
+       for (i = 0; i < len; i++) {
+               tmp = snr_lut[i].snr;
 
-       buf[0] = (u8) ((adc_cw & 0x000000ff));
-       buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8);
-       buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16);
+               if (snr_val < snr_lut[i].val)
+                       break;
+       }
+       state->snr = tmp * 10; /* dB/10 */
 
-       deb_info("%s: adc_cw:", __func__);
-       debug_dump(buf, sizeof(buf), deb_info);
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret = 0;
+       u8 buf[2], rf_gain, if_gain;
+       int signal_strength;
+
+       dbg("%s", __func__);
+
+       if (!state->signal_strength_en)
+               return 0;
+
+       ret = af9013_rd_regs(state, 0xd07c, buf, 2);
+       if (ret)
+               goto err;
+
+       rf_gain = buf[0];
+       if_gain = buf[1];
+
+       signal_strength = (0xffff / \
+               (9 * (state->rf_50 + state->if_50) - \
+               11 * (state->rf_80 + state->if_80))) * \
+               (10 * (rf_gain + if_gain) - \
+               11 * (state->rf_80 + state->if_80));
+       if (signal_strength < 0)
+               signal_strength = 0;
+       else if (signal_strength > 0xffff)
+               signal_strength = 0xffff;
+
+       state->signal_strength = signal_strength;
 
-       /* program */
-       for (i = 0; i < sizeof(buf); i++) {
-               ret = af9013_write_reg(state, 0xd180 + i, buf[i]);
-               if (ret)
-                       goto error;
-       }
-       ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp);
-error:
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
-static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw)
+static void af9013_statistics_work(struct work_struct *work)
 {
        int ret;
-       u16 addr;
-       u8 buf[3], i, j;
-       u32 adc_freq, freq_cw;
-       s8 bfs_spec_inv;
-       int if_sample_freq;
-
-       for (j = 0; j < 3; j++) {
-               if (j == 0) {
-                       addr = 0xd140; /* fcw normal */
-                       bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
-               } else if (j == 1) {
-                       addr = 0x9be7; /* fcw dummy ram */
-                       bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
-               } else {
-                       addr = 0x9bea; /* fcw inverted */
-                       bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1;
-               }
+       struct af9013_state *state = container_of(work,
+               struct af9013_state, statistics_work.work);
+       unsigned int next_msec;
+
+       /* update only signal strength when demod is not locked */
+       if (!(state->fe_status & FE_HAS_LOCK)) {
+               state->statistics_step = 0;
+               state->ber = 0;
+               state->snr = 0;
+       }
+
+       switch (state->statistics_step) {
+       default:
+               state->statistics_step = 0;
+       case 0:
+               ret = af9013_statistics_signal_strength(&state->fe);
+               state->statistics_step++;
+               next_msec = 300;
+               break;
+       case 1:
+               ret = af9013_statistics_snr_start(&state->fe);
+               state->statistics_step++;
+               next_msec = 200;
+               break;
+       case 2:
+               ret = af9013_statistics_ber_unc_start(&state->fe);
+               state->statistics_step++;
+               next_msec = 1000;
+               break;
+       case 3:
+               ret = af9013_statistics_snr_result(&state->fe);
+               state->statistics_step++;
+               next_msec = 400;
+               break;
+       case 4:
+               ret = af9013_statistics_ber_unc_result(&state->fe);
+               state->statistics_step++;
+               next_msec = 100;
+               break;
+       }
 
-               adc_freq       = state->config.adc_clock * 1000;
-               if_sample_freq = state->config.tuner_if * 1000;
+       schedule_delayed_work(&state->statistics_work,
+               msecs_to_jiffies(next_msec));
 
-               /* TDA18271 uses different sampling freq for every bw */
-               if (state->config.tuner == AF9013_TUNER_TDA18271) {
-                       switch (bw) {
-                       case BANDWIDTH_6_MHZ:
-                               if_sample_freq = 3300000; /* 3.3 MHz */
-                               break;
-                       case BANDWIDTH_7_MHZ:
-                               if_sample_freq = 3500000; /* 3.5 MHz */
-                               break;
-                       case BANDWIDTH_8_MHZ:
-                       default:
-                               if_sample_freq = 4000000; /* 4.0 MHz */
-                               break;
-                       }
-               } else if (state->config.tuner == AF9013_TUNER_TDA18218) {
-                       switch (bw) {
-                       case BANDWIDTH_6_MHZ:
-                               if_sample_freq = 3000000; /* 3 MHz */
-                               break;
-                       case BANDWIDTH_7_MHZ:
-                               if_sample_freq = 3500000; /* 3.5 MHz */
-                               break;
-                       case BANDWIDTH_8_MHZ:
-                       default:
-                               if_sample_freq = 4000000; /* 4 MHz */
+       return;
+}
+
+static int af9013_get_tune_settings(struct dvb_frontend *fe,
+       struct dvb_frontend_tune_settings *fesettings)
+{
+       fesettings->min_delay_ms = 800;
+       fesettings->step_size = 0;
+       fesettings->max_drift = 0;
+
+       return 0;
+}
+
+static int af9013_set_frontend(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret, i, sampling_freq;
+       bool auto_mode, spec_inv;
+       u8 buf[6];
+       u32 if_frequency, freq_cw;
+
+       dbg("%s: frequency=%d bandwidth_hz=%d", __func__,
+               c->frequency, c->bandwidth_hz);
+
+       /* program tuner */
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe);
+
+       /* program CFOE coefficients */
+       if (c->bandwidth_hz != state->bandwidth_hz) {
+               for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
+                       if (coeff_lut[i].clock == state->config.clock &&
+                               coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
                                break;
                        }
                }
 
-               while (if_sample_freq > (adc_freq / 2))
-                       if_sample_freq = if_sample_freq - adc_freq;
+               ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val,
+                       sizeof(coeff_lut[i].val));
+       }
 
-               if (if_sample_freq >= 0)
-                       bfs_spec_inv = bfs_spec_inv * (-1);
+       /* program frequency control */
+       if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) {
+               /* get used IF frequency */
+               if (fe->ops.tuner_ops.get_if_frequency)
+                       fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
                else
-                       if_sample_freq = if_sample_freq * (-1);
+                       if_frequency = state->config.if_frequency;
 
-               freq_cw = af913_div(if_sample_freq, adc_freq, 23ul);
+               sampling_freq = if_frequency;
 
-               if (bfs_spec_inv == -1)
-                       freq_cw = 0x00800000 - freq_cw;
+               while (sampling_freq > (state->config.clock / 2))
+                       sampling_freq -= state->config.clock;
 
-               buf[0] = (u8) ((freq_cw & 0x000000ff));
-               buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8);
-               buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16);
+               if (sampling_freq < 0) {
+                       sampling_freq *= -1;
+                       spec_inv = state->config.spec_inv;
+               } else {
+                       spec_inv = !state->config.spec_inv;
+               }
 
+               freq_cw = af913_div(sampling_freq, state->config.clock, 23);
 
-               deb_info("%s: freq_cw:", __func__);
-               debug_dump(buf, sizeof(buf), deb_info);
+               if (spec_inv)
+                       freq_cw = 0x800000 - freq_cw;
 
-               /* program */
-               for (i = 0; i < sizeof(buf); i++) {
-                       ret = af9013_write_reg(state, addr++, buf[i]);
-                       if (ret)
-                               goto error;
-               }
+               buf[0] = (freq_cw >>  0) & 0xff;
+               buf[1] = (freq_cw >>  8) & 0xff;
+               buf[2] = (freq_cw >> 16) & 0x7f;
+
+               freq_cw = 0x800000 - freq_cw;
+
+               buf[3] = (freq_cw >>  0) & 0xff;
+               buf[4] = (freq_cw >>  8) & 0xff;
+               buf[5] = (freq_cw >> 16) & 0x7f;
+
+               ret = af9013_wr_regs(state, 0xd140, buf, 3);
+               if (ret)
+                       goto err;
+
+               ret = af9013_wr_regs(state, 0x9be7, buf, 6);
+               if (ret)
+                       goto err;
        }
-error:
-       return ret;
-}
 
-static int af9013_set_ofdm_params(struct af9013_state *state,
-       struct dvb_ofdm_parameters *params, u8 *auto_mode)
-{
-       int ret;
-       u8 i, buf[3] = {0, 0, 0};
-       *auto_mode = 0; /* set if parameters are requested to auto set */
+       /* clear TPS lock flag */
+       ret = af9013_wr_reg_bits(state, 0xd330, 3, 1, 1);
+       if (ret)
+               goto err;
 
-       /* Try auto-detect transmission parameters in case of AUTO requested or
-          garbage parameters given by application for compatibility.
-          MPlayer seems to provide garbage parameters currently. */
+       /* clear MPEG2 lock flag */
+       ret = af9013_wr_reg_bits(state, 0xd507, 6, 1, 0);
+       if (ret)
+               goto err;
 
-       switch (params->transmission_mode) {
+       /* empty channel function */
+       ret = af9013_wr_reg_bits(state, 0x9bfe, 0, 1, 0);
+       if (ret)
+               goto err;
+
+       /* empty DVB-T channel function */
+       ret = af9013_wr_reg_bits(state, 0x9bc2, 0, 1, 0);
+       if (ret)
+               goto err;
+
+       /* transmission parameters */
+       auto_mode = false;
+       memset(buf, 0, 3);
+
+       switch (c->transmission_mode) {
        case TRANSMISSION_MODE_AUTO:
-               *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case TRANSMISSION_MODE_2K:
                break;
        case TRANSMISSION_MODE_8K:
                buf[0] |= (1 << 0);
                break;
        default:
-               deb_info("%s: invalid transmission_mode\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid transmission_mode", __func__);
+               auto_mode = 1;
        }
 
-       switch (params->guard_interval) {
+       switch (c->guard_interval) {
        case GUARD_INTERVAL_AUTO:
-               *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case GUARD_INTERVAL_1_32:
                break;
        case GUARD_INTERVAL_1_16:
@@ -427,13 +699,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[0] |= (3 << 2);
                break;
        default:
-               deb_info("%s: invalid guard_interval\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid guard_interval", __func__);
+               auto_mode = 1;
        }
 
-       switch (params->hierarchy_information) {
+       switch (c->hierarchy) {
        case HIERARCHY_AUTO:
-               *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case HIERARCHY_NONE:
                break;
        case HIERARCHY_1:
@@ -446,13 +719,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[0] |= (3 << 4);
                break;
        default:
-               deb_info("%s: invalid hierarchy_information\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid hierarchy", __func__);
+               auto_mode = 1;
        };
 
-       switch (params->constellation) {
+       switch (c->modulation) {
        case QAM_AUTO:
-               *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case QPSK:
                break;
        case QAM_16:
@@ -462,16 +736,17 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[1] |= (2 << 6);
                break;
        default:
-               deb_info("%s: invalid constellation\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid modulation", __func__);
+               auto_mode = 1;
        }
 
        /* Use HP. How and which case we can switch to LP? */
        buf[1] |= (1 << 4);
 
-       switch (params->code_rate_HP) {
+       switch (c->code_rate_HP) {
        case FEC_AUTO:
-               *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case FEC_1_2:
                break;
        case FEC_2_3:
@@ -487,16 +762,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[2] |= (4 << 0);
                break;
        default:
-               deb_info("%s: invalid code_rate_HP\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid code_rate_HP", __func__);
+               auto_mode = 1;
        }
 
-       switch (params->code_rate_LP) {
+       switch (c->code_rate_LP) {
        case FEC_AUTO:
-       /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO
-          by dvb_frontend.c for compatibility */
-               if (params->hierarchy_information != HIERARCHY_NONE)
-                       *auto_mode = 1;
+               auto_mode = 1;
+               break;
        case FEC_1_2:
                break;
        case FEC_2_3:
@@ -512,709 +785,373 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[2] |= (4 << 3);
                break;
        case FEC_NONE:
-               if (params->hierarchy_information == HIERARCHY_AUTO)
-                       break;
+               break;
        default:
-               deb_info("%s: invalid code_rate_LP\n", __func__);
-               *auto_mode = 1;
+               dbg("%s: invalid code_rate_LP", __func__);
+               auto_mode = 1;
        }
 
-       switch (params->bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                buf[1] |= (1 << 2);
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                buf[1] |= (2 << 2);
                break;
        default:
-               deb_info("%s: invalid bandwidth\n", __func__);
-               buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */
-       }
-
-       /* program */
-       for (i = 0; i < sizeof(buf); i++) {
-               ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]);
-               if (ret)
-                       break;
+               dbg("%s: invalid bandwidth_hz", __func__);
+               ret = -EINVAL;
+               goto err;
        }
 
-       return ret;
-}
-
-static int af9013_reset(struct af9013_state *state, u8 sleep)
-{
-       int ret;
-       u8 tmp, i;
-       deb_info("%s\n", __func__);
-
-       /* enable OFDM reset */
-       ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1);
+       ret = af9013_wr_regs(state, 0xd3c0, buf, 3);
        if (ret)
-               goto error;
+               goto err;
 
-       /* start reset mechanism */
-       ret = af9013_write_reg(state, 0xaeff, 1);
-       if (ret)
-               goto error;
-
-       /* reset is done when bit 1 is set */
-       for (i = 0; i < 150; i++) {
-               ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp);
-               if (ret)
-                       goto error;
-               if (tmp)
-                       break; /* reset done */
-               msleep(10);
-       }
-       if (!tmp)
-               return -ETIMEDOUT;
-
-       /* don't clear reset when going to sleep */
-       if (!sleep) {
-               /* clear OFDM reset */
-               ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+       if (auto_mode) {
+               /* clear easy mode flag */
+               ret = af9013_wr_reg(state, 0xaefd, 0);
                if (ret)
-                       goto error;
+                       goto err;
 
-               /* disable OFDM reset */
-               ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
-       }
-error:
-       return ret;
-}
-
-static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
-{
-       int ret;
-       deb_info("%s: onoff:%d\n", __func__, onoff);
-
-       if (onoff) {
-               /* power on */
-               ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0);
-               if (ret)
-                       goto error;
-               ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
-               if (ret)
-                       goto error;
-               ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+               dbg("%s: auto params", __func__);
        } else {
-               /* power off */
-               ret = af9013_reset(state, 1);
+               /* set easy mode flag */
+               ret = af9013_wr_reg(state, 0xaefd, 1);
                if (ret)
-                       goto error;
-               ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1);
-       }
-error:
-       return ret;
-}
-
-static int af9013_lock_led(struct af9013_state *state, u8 onoff)
-{
-       deb_info("%s: onoff:%d\n", __func__, onoff);
-
-       return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff);
-}
-
-static int af9013_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       u8 auto_mode; /* auto set TPS */
-
-       deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
-               params->u.ofdm.bandwidth);
-
-       state->frequency = params->frequency;
-
-       /* program tuner */
-       if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, params);
-
-       /* program CFOE coefficients */
-       ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
-       if (ret)
-               goto error;
-
-       /* program frequency control */
-       ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth);
-       if (ret)
-               goto error;
-
-       /* clear TPS lock flag (inverted flag) */
-       ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1);
-       if (ret)
-               goto error;
-
-       /* clear MPEG2 lock flag */
-       ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0);
-       if (ret)
-               goto error;
-
-       /* empty channel function */
-       ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0);
-       if (ret)
-               goto error;
-
-       /* empty DVB-T channel function */
-       ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0);
-       if (ret)
-               goto error;
+                       goto err;
 
-       /* program TPS and bandwidth, check if auto mode needed */
-       ret = af9013_set_ofdm_params(state, &params->u.ofdm, &auto_mode);
-       if (ret)
-               goto error;
-
-       if (auto_mode) {
-               /* clear easy mode flag */
-               ret = af9013_write_reg(state, 0xaefd, 0);
-               deb_info("%s: auto TPS\n", __func__);
-       } else {
-               /* set easy mode flag */
-               ret = af9013_write_reg(state, 0xaefd, 1);
+               ret = af9013_wr_reg(state, 0xaefe, 0);
                if (ret)
-                       goto error;
-               ret = af9013_write_reg(state, 0xaefe, 0);
-               deb_info("%s: manual TPS\n", __func__);
+                       goto err;
+
+               dbg("%s: manual params", __func__);
        }
-       if (ret)
-               goto error;
 
-       /* everything is set, lets try to receive channel - OFSM GO! */
-       ret = af9013_write_reg(state, 0xffff, 0);
+       /* tune */
+       ret = af9013_wr_reg(state, 0xffff, 0);
        if (ret)
-               goto error;
+               goto err;
+
+       state->bandwidth_hz = c->bandwidth_hz;
+       state->set_frontend_jiffies = jiffies;
+       state->first_tune = false;
 
-error:
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
-static int af9013_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int af9013_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct af9013_state *state = fe->demodulator_priv;
        int ret;
-       u8 i, buf[3];
-       deb_info("%s\n", __func__);
+       u8 buf[3];
 
-       /* read TPS registers */
-       for (i = 0; i < 3; i++) {
-               ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
+       dbg("%s", __func__);
+
+       ret = af9013_rd_regs(state, 0xd3c0, buf, 3);
+       if (ret)
+               goto err;
 
        switch ((buf[1] >> 6) & 3) {
        case 0:
-               p->u.ofdm.constellation = QPSK;
+               c->modulation = QPSK;
                break;
        case 1:
-               p->u.ofdm.constellation = QAM_16;
+               c->modulation = QAM_16;
                break;
        case 2:
-               p->u.ofdm.constellation = QAM_64;
+               c->modulation = QAM_64;
                break;
        }
 
        switch ((buf[0] >> 0) & 3) {
        case 0:
-               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               c->transmission_mode = TRANSMISSION_MODE_2K;
                break;
        case 1:
-               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               c->transmission_mode = TRANSMISSION_MODE_8K;
        }
 
        switch ((buf[0] >> 2) & 3) {
        case 0:
-               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               c->guard_interval = GUARD_INTERVAL_1_32;
                break;
        case 1:
-               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               c->guard_interval = GUARD_INTERVAL_1_16;
                break;
        case 2:
-               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               c->guard_interval = GUARD_INTERVAL_1_8;
                break;
        case 3:
-               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               c->guard_interval = GUARD_INTERVAL_1_4;
                break;
        }
 
        switch ((buf[0] >> 4) & 7) {
        case 0:
-               p->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               c->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               p->u.ofdm.hierarchy_information = HIERARCHY_1;
+               c->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               p->u.ofdm.hierarchy_information = HIERARCHY_2;
+               c->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               p->u.ofdm.hierarchy_information = HIERARCHY_4;
+               c->hierarchy = HIERARCHY_4;
                break;
        }
 
        switch ((buf[2] >> 0) & 7) {
        case 0:
-               p->u.ofdm.code_rate_HP = FEC_1_2;
+               c->code_rate_HP = FEC_1_2;
                break;
        case 1:
-               p->u.ofdm.code_rate_HP = FEC_2_3;
-               break;
-       case 2:
-               p->u.ofdm.code_rate_HP = FEC_3_4;
-               break;
-       case 3:
-               p->u.ofdm.code_rate_HP = FEC_5_6;
-               break;
-       case 4:
-               p->u.ofdm.code_rate_HP = FEC_7_8;
-               break;
-       }
-
-       switch ((buf[2] >> 3) & 7) {
-       case 0:
-               p->u.ofdm.code_rate_LP = FEC_1_2;
-               break;
-       case 1:
-               p->u.ofdm.code_rate_LP = FEC_2_3;
-               break;
-       case 2:
-               p->u.ofdm.code_rate_LP = FEC_3_4;
-               break;
-       case 3:
-               p->u.ofdm.code_rate_LP = FEC_5_6;
-               break;
-       case 4:
-               p->u.ofdm.code_rate_LP = FEC_7_8;
-               break;
-       }
-
-       switch ((buf[1] >> 2) & 3) {
-       case 0:
-               p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
-               break;
-       case 1:
-               p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
-               break;
-       case 2:
-               p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
-               break;
-       }
-
-       p->inversion = INVERSION_AUTO;
-       p->frequency = state->frequency;
-
-error:
-       return ret;
-}
-
-static int af9013_update_ber_unc(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       u8 buf[3], i;
-       u32 error_bit_count = 0;
-       u32 total_bit_count = 0;
-       u32 abort_packet_count = 0;
-
-       state->ber = 0;
-
-       /* check if error bit count is ready */
-       ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]);
-       if (ret)
-               goto error;
-       if (!buf[0])
-               goto exit;
-
-       /* get RSD packet abort count */
-       for (i = 0; i < 2; i++) {
-               ret = af9013_read_reg(state, 0xd38a + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
-       abort_packet_count = (buf[1] << 8) + buf[0];
-
-       /* get error bit count */
-       for (i = 0; i < 3; i++) {
-               ret = af9013_read_reg(state, 0xd387 + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
-       error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0];
-       error_bit_count = error_bit_count - abort_packet_count * 8 * 8;
-
-       /* get used RSD counting period (10000 RSD packets used) */
-       for (i = 0; i < 2; i++) {
-               ret = af9013_read_reg(state, 0xd385 + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
-       total_bit_count = (buf[1] << 8) + buf[0];
-       total_bit_count = total_bit_count - abort_packet_count;
-       total_bit_count = total_bit_count * 204 * 8;
-
-       if (total_bit_count)
-               state->ber = error_bit_count * 1000000000 / total_bit_count;
-
-       state->ucblocks += abort_packet_count;
-
-       deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__,
-               error_bit_count, total_bit_count, abort_packet_count);
-
-       /* set BER counting range */
-       ret = af9013_write_reg(state, 0xd385, 10000 & 0xff);
-       if (ret)
-               goto error;
-       ret = af9013_write_reg(state, 0xd386, 10000 >> 8);
-       if (ret)
-               goto error;
-       /* reset and start BER counter */
-       ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1);
-       if (ret)
-               goto error;
-
-exit:
-error:
-       return ret;
-}
-
-static int af9013_update_snr(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       u8 buf[3], i, len;
-       u32 quant = 0;
-       struct snr_table *uninitialized_var(snr_table);
-
-       /* check if quantizer ready (for snr) */
-       ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]);
-       if (ret)
-               goto error;
-       if (buf[0]) {
-               /* quantizer ready - read it */
-               for (i = 0; i < 3; i++) {
-                       ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]);
-                       if (ret)
-                               goto error;
-               }
-               quant = (buf[2] << 16) + (buf[1] << 8) + buf[0];
-
-               /* read current constellation */
-               ret = af9013_read_reg(state, 0xd3c1, &buf[0]);
-               if (ret)
-                       goto error;
-
-               switch ((buf[0] >> 6) & 3) {
-               case 0:
-                       len = ARRAY_SIZE(qpsk_snr_table);
-                       snr_table = qpsk_snr_table;
-                       break;
-               case 1:
-                       len = ARRAY_SIZE(qam16_snr_table);
-                       snr_table = qam16_snr_table;
-                       break;
-               case 2:
-                       len = ARRAY_SIZE(qam64_snr_table);
-                       snr_table = qam64_snr_table;
-                       break;
-               default:
-                       len = 0;
-                       break;
-               }
-
-               if (len) {
-                       for (i = 0; i < len; i++) {
-                               if (quant < snr_table[i].val) {
-                                       state->snr = snr_table[i].snr * 10;
-                                       break;
-                               }
-                       }
-               }
-
-               /* set quantizer super frame count */
-               ret = af9013_write_reg(state, 0xd2e2, 1);
-               if (ret)
-                       goto error;
-
-               /* check quantizer availability */
-               for (i = 0; i < 10; i++) {
-                       msleep(10);
-                       ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1,
-                               &buf[0]);
-                       if (ret)
-                               goto error;
-                       if (!buf[0])
-                               break;
-               }
-
-               /* reset quantizer */
-               ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1);
-               if (ret)
-                       goto error;
+               c->code_rate_HP = FEC_2_3;
+               break;
+       case 2:
+               c->code_rate_HP = FEC_3_4;
+               break;
+       case 3:
+               c->code_rate_HP = FEC_5_6;
+               break;
+       case 4:
+               c->code_rate_HP = FEC_7_8;
+               break;
        }
 
-error:
-       return ret;
-}
-
-static int af9013_update_signal_strength(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret = 0;
-       u8 rf_gain, if_gain;
-       int signal_strength;
-
-       deb_info("%s\n", __func__);
+       switch ((buf[2] >> 3) & 7) {
+       case 0:
+               c->code_rate_LP = FEC_1_2;
+               break;
+       case 1:
+               c->code_rate_LP = FEC_2_3;
+               break;
+       case 2:
+               c->code_rate_LP = FEC_3_4;
+               break;
+       case 3:
+               c->code_rate_LP = FEC_5_6;
+               break;
+       case 4:
+               c->code_rate_LP = FEC_7_8;
+               break;
+       }
 
-       if (state->signal_strength_en) {
-               ret = af9013_read_reg(state, 0xd07c, &rf_gain);
-               if (ret)
-                       goto error;
-               ret = af9013_read_reg(state, 0xd07d, &if_gain);
-               if (ret)
-                       goto error;
-               signal_strength = (0xffff / \
-                       (9 * (state->rf_50 + state->if_50) - \
-                       11 * (state->rf_80 + state->if_80))) * \
-                       (10 * (rf_gain + if_gain) - \
-                       11 * (state->rf_80 + state->if_80));
-               if (signal_strength < 0)
-                       signal_strength = 0;
-               else if (signal_strength > 0xffff)
-                       signal_strength = 0xffff;
-
-               state->signal_strength = signal_strength;
-       } else {
-               state->signal_strength = 0;
+       switch ((buf[1] >> 2) & 3) {
+       case 0:
+               c->bandwidth_hz = 6000000;
+               break;
+       case 1:
+               c->bandwidth_hz = 7000000;
+               break;
+       case 2:
+               c->bandwidth_hz = 8000000;
+               break;
        }
 
-error:
        return ret;
-}
-
-static int af9013_update_statistics(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-
-       if (time_before(jiffies, state->next_statistics_check))
-               return 0;
-
-       /* set minimum statistic update interval */
-       state->next_statistics_check = jiffies + msecs_to_jiffies(1200);
-
-       ret = af9013_update_signal_strength(fe);
-       if (ret)
-               goto error;
-       ret = af9013_update_snr(fe);
-       if (ret)
-               goto error;
-       ret = af9013_update_ber_unc(fe);
-       if (ret)
-               goto error;
-
-error:
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
-static int af9013_get_tune_settings(struct dvb_frontend *fe,
-       struct dvb_frontend_tune_settings *fesettings)
-{
-       fesettings->min_delay_ms = 800;
-       fesettings->step_size = 0;
-       fesettings->max_drift = 0;
-
-       return 0;
-}
-
 static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct af9013_state *state = fe->demodulator_priv;
-       int ret = 0;
+       int ret;
        u8 tmp;
-       *status = 0;
+
+       /*
+        * Return status from the cache if it is younger than 2000ms with the
+        * exception of last tune is done during 4000ms.
+        */
+       if (time_is_after_jiffies(
+               state->read_status_jiffies + msecs_to_jiffies(2000)) &&
+               time_is_before_jiffies(
+               state->set_frontend_jiffies + msecs_to_jiffies(4000))
+       ) {
+                       *status = state->fe_status;
+                       return 0;
+       } else {
+               *status = 0;
+       }
 
        /* MPEG2 lock */
-       ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
+       ret = af9013_rd_reg_bits(state, 0xd507, 6, 1, &tmp);
        if (ret)
-               goto error;
+               goto err;
+
        if (tmp)
                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
                        FE_HAS_SYNC | FE_HAS_LOCK;
 
        if (!*status) {
                /* TPS lock */
-               ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
+               ret = af9013_rd_reg_bits(state, 0xd330, 3, 1, &tmp);
                if (ret)
-                       goto error;
+                       goto err;
+
                if (tmp)
                        *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
                                FE_HAS_VITERBI;
        }
 
-       if (!*status) {
-               /* CFO lock */
-               ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
-               if (ret)
-                       goto error;
-               if (tmp)
-                       *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-       }
-
-       if (!*status) {
-               /* SFOE lock */
-               ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
-               if (ret)
-                       goto error;
-               if (tmp)
-                       *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-       }
-
-       if (!*status) {
-               /* AGC lock */
-               ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
-               if (ret)
-                       goto error;
-               if (tmp)
-                       *status |= FE_HAS_SIGNAL;
-       }
-
-       ret = af9013_update_statistics(fe);
+       state->fe_status = *status;
+       state->read_status_jiffies = jiffies;
 
-error:
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
-
-static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
+static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       ret = af9013_update_statistics(fe);
-       *ber = state->ber;
-       return ret;
+       *snr = state->snr;
+       return 0;
 }
 
 static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       ret = af9013_update_statistics(fe);
        *strength = state->signal_strength;
-       return ret;
+       return 0;
 }
 
-static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
        struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       ret = af9013_update_statistics(fe);
-       *snr = state->snr;
-       return ret;
+       *ber = state->ber;
+       return 0;
 }
 
 static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
        struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       ret = af9013_update_statistics(fe);
        *ucblocks = state->ucblocks;
-       return ret;
-}
-
-static int af9013_sleep(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       int ret;
-       deb_info("%s\n", __func__);
-
-       ret = af9013_lock_led(state, 0);
-       if (ret)
-               goto error;
-
-       ret = af9013_power_ctrl(state, 0);
-error:
-       return ret;
+       return 0;
 }
 
 static int af9013_init(struct dvb_frontend *fe)
 {
        struct af9013_state *state = fe->demodulator_priv;
        int ret, i, len;
-       u8 tmp0, tmp1;
-       struct regdesc *init;
-       deb_info("%s\n", __func__);
+       u8 buf[3], tmp;
+       u32 adc_cw;
+       const struct af9013_reg_bit *init;
 
-       /* reset OFDM */
-       ret = af9013_reset(state, 0);
-       if (ret)
-               goto error;
+       dbg("%s", __func__);
 
        /* power on */
        ret = af9013_power_ctrl(state, 1);
        if (ret)
-               goto error;
+               goto err;
 
        /* enable ADC */
-       ret = af9013_write_reg(state, 0xd73a, 0xa4);
+       ret = af9013_wr_reg(state, 0xd73a, 0xa4);
        if (ret)
-               goto error;
+               goto err;
 
        /* write API version to firmware */
-       for (i = 0; i < sizeof(state->config.api_version); i++) {
-               ret = af9013_write_reg(state, 0x9bf2 + i,
-                       state->config.api_version[i]);
-               if (ret)
-                       goto error;
-       }
+       ret = af9013_wr_regs(state, 0x9bf2, state->config.api_version, 4);
+       if (ret)
+               goto err;
 
        /* program ADC control */
-       ret = af9013_set_adc_ctrl(state);
+       switch (state->config.clock) {
+       case 28800000: /* 28.800 MHz */
+               tmp = 0;
+               break;
+       case 20480000: /* 20.480 MHz */
+               tmp = 1;
+               break;
+       case 28000000: /* 28.000 MHz */
+               tmp = 2;
+               break;
+       case 25000000: /* 25.000 MHz */
+               tmp = 3;
+               break;
+       default:
+               err("invalid clock");
+               return -EINVAL;
+       }
+
+       adc_cw = af913_div(state->config.clock, 1000000ul, 19);
+       buf[0] = (adc_cw >>  0) & 0xff;
+       buf[1] = (adc_cw >>  8) & 0xff;
+       buf[2] = (adc_cw >> 16) & 0xff;
+
+       ret = af9013_wr_regs(state, 0xd180, buf, 3);
+       if (ret)
+               goto err;
+
+       ret = af9013_wr_reg_bits(state, 0x9bd2, 0, 4, tmp);
        if (ret)
-               goto error;
+               goto err;
 
        /* set I2C master clock */
-       ret = af9013_write_reg(state, 0xd416, 0x14);
+       ret = af9013_wr_reg(state, 0xd416, 0x14);
        if (ret)
-               goto error;
+               goto err;
 
        /* set 16 embx */
-       ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1);
+       ret = af9013_wr_reg_bits(state, 0xd700, 1, 1, 1);
        if (ret)
-               goto error;
+               goto err;
 
        /* set no trigger */
-       ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0);
+       ret = af9013_wr_reg_bits(state, 0xd700, 2, 1, 0);
        if (ret)
-               goto error;
+               goto err;
 
        /* set read-update bit for constellation */
-       ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1);
+       ret = af9013_wr_reg_bits(state, 0xd371, 1, 1, 1);
        if (ret)
-               goto error;
+               goto err;
 
-       /* enable FEC monitor */
-       ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1);
+       /* settings for mp2if */
+       if (state->config.ts_mode == AF9013_TS_USB) {
+               /* AF9015 split PSB to 1.5k + 0.5k */
+               ret = af9013_wr_reg_bits(state, 0xd50b, 2, 1, 1);
+               if (ret)
+                       goto err;
+       } else {
+               /* AF9013 change the output bit to data7 */
+               ret = af9013_wr_reg_bits(state, 0xd500, 3, 1, 1);
+               if (ret)
+                       goto err;
+
+               /* AF9013 set mpeg to full speed */
+               ret = af9013_wr_reg_bits(state, 0xd502, 4, 1, 1);
+               if (ret)
+                       goto err;
+       }
+
+       ret = af9013_wr_reg_bits(state, 0xd520, 4, 1, 1);
        if (ret)
-               goto error;
+               goto err;
 
        /* load OFSM settings */
-       deb_info("%s: load ofsm settings\n", __func__);
+       dbg("%s: load ofsm settings", __func__);
        len = ARRAY_SIZE(ofsm_init);
        init = ofsm_init;
        for (i = 0; i < len; i++) {
-               ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+               ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
                        init[i].len, init[i].val);
                if (ret)
-                       goto error;
+                       goto err;
        }
 
        /* load tuner specific settings */
-       deb_info("%s: load tuner specific settings\n", __func__);
+       dbg("%s: load tuner specific settings", __func__);
        switch (state->config.tuner) {
        case AF9013_TUNER_MXL5003D:
                len = ARRAY_SIZE(tuner_init_mxl5003d);
@@ -1260,65 +1197,133 @@ static int af9013_init(struct dvb_frontend *fe)
        }
 
        for (i = 0; i < len; i++) {
-               ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+               ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
                        init[i].len, init[i].val);
                if (ret)
-                       goto error;
+                       goto err;
        }
 
-       /* set TS mode */
-       deb_info("%s: setting ts mode\n", __func__);
-       tmp0 = 0; /* parallel mode */
-       tmp1 = 0; /* serial mode */
-       switch (state->config.output_mode) {
-       case AF9013_OUTPUT_MODE_PARALLEL:
-               tmp0 = 1;
-               break;
-       case AF9013_OUTPUT_MODE_SERIAL:
-               tmp1 = 1;
-               break;
-       case AF9013_OUTPUT_MODE_USB:
-               /* usb mode for AF9015 */
-       default:
-               break;
-       }
-       ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */
+       /* TS mode */
+       ret = af9013_wr_reg_bits(state, 0xd500, 1, 2, state->config.ts_mode);
        if (ret)
-               goto error;
-       ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */
-       if (ret)
-               goto error;
+               goto err;
 
        /* enable lock led */
-       ret = af9013_lock_led(state, 1);
+       ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 1);
        if (ret)
-               goto error;
+               goto err;
 
-       /* read values needed for signal strength calculation */
-       ret = af9013_read_reg_bits(state, 0x9bee, 0, 1,
-               &state->signal_strength_en);
-       if (ret)
-               goto error;
+       /* check if we support signal strength */
+       if (!state->signal_strength_en) {
+               ret = af9013_rd_reg_bits(state, 0x9bee, 0, 1,
+                       &state->signal_strength_en);
+               if (ret)
+                       goto err;
+       }
 
-       if (state->signal_strength_en) {
-               ret = af9013_read_reg(state, 0x9bbd, &state->rf_50);
+       /* read values needed for signal strength calculation */
+       if (state->signal_strength_en && !state->rf_50) {
+               ret = af9013_rd_reg(state, 0x9bbd, &state->rf_50);
                if (ret)
-                       goto error;
-               ret = af9013_read_reg(state, 0x9bd0, &state->rf_80);
+                       goto err;
+
+               ret = af9013_rd_reg(state, 0x9bd0, &state->rf_80);
                if (ret)
-                       goto error;
-               ret = af9013_read_reg(state, 0x9be2, &state->if_50);
+                       goto err;
+
+               ret = af9013_rd_reg(state, 0x9be2, &state->if_50);
                if (ret)
-                       goto error;
-               ret = af9013_read_reg(state, 0x9be4, &state->if_80);
+                       goto err;
+
+               ret = af9013_rd_reg(state, 0x9be4, &state->if_80);
                if (ret)
-                       goto error;
+                       goto err;
        }
 
-error:
+       /* SNR */
+       ret = af9013_wr_reg(state, 0xd2e2, 1);
+       if (ret)
+               goto err;
+
+       /* BER / UCB */
+       buf[0] = (10000 >> 0) & 0xff;
+       buf[1] = (10000 >> 8) & 0xff;
+       ret = af9013_wr_regs(state, 0xd385, buf, 2);
+       if (ret)
+               goto err;
+
+       /* enable FEC monitor */
+       ret = af9013_wr_reg_bits(state, 0xd392, 1, 1, 1);
+       if (ret)
+               goto err;
+
+       state->first_tune = true;
+       schedule_delayed_work(&state->statistics_work, msecs_to_jiffies(400));
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_sleep(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+
+       dbg("%s", __func__);
+
+       /* stop statistics polling */
+       cancel_delayed_work_sync(&state->statistics_work);
+
+       /* disable lock led */
+       ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 0);
+       if (ret)
+               goto err;
+
+       /* power off */
+       ret = af9013_power_ctrl(state, 0);
+       if (ret)
+               goto err;
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       int ret;
+       struct af9013_state *state = fe->demodulator_priv;
+
+       dbg("%s: enable=%d", __func__, enable);
+
+       /* gate already open or close */
+       if (state->i2c_gate_state == enable)
+               return 0;
+
+       if (state->config.ts_mode == AF9013_TS_USB)
+               ret = af9013_wr_reg_bits(state, 0xd417, 3, 1, enable);
+       else
+               ret = af9013_wr_reg_bits(state, 0xd607, 2, 1, enable);
+       if (ret)
+               goto err;
+
+       state->i2c_gate_state = enable;
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
        return ret;
 }
 
+static void af9013_release(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
 static struct dvb_frontend_ops af9013_ops;
 
 static int af9013_download_firmware(struct af9013_state *state)
@@ -1332,11 +1337,11 @@ static int af9013_download_firmware(struct af9013_state *state)
 
        msleep(100);
        /* check whether firmware is already running */
-       ret = af9013_read_reg(state, 0x98be, &val);
+       ret = af9013_rd_reg(state, 0x98be, &val);
        if (ret)
-               goto error;
+               goto err;
        else
-               deb_info("%s: firmware status:%02x\n", __func__, val);
+               dbg("%s: firmware status=%02x", __func__, val);
 
        if (val == 0x0c) /* fw is running, no need for download */
                goto exit;
@@ -1351,7 +1356,7 @@ static int af9013_download_firmware(struct af9013_state *state)
                        "Please see linux/Documentation/dvb/ for more details" \
                        " on firmware-problems. (%d)",
                        fw_file, ret);
-               goto error;
+               goto err;
        }
 
        info("downloading firmware from file '%s'", fw_file);
@@ -1369,7 +1374,7 @@ static int af9013_download_firmware(struct af9013_state *state)
        ret = af9013_write_ofsm_regs(state, 0x50fc,
                fw_params, sizeof(fw_params));
        if (ret)
-               goto error_release;
+               goto err_release;
 
        #define FW_ADDR 0x5100 /* firmware start address */
        #define LEN_MAX 16 /* max packet size */
@@ -1383,24 +1388,24 @@ static int af9013_download_firmware(struct af9013_state *state)
                        (u8 *) &fw->data[fw->size - remaining], len);
                if (ret) {
                        err("firmware download failed:%d", ret);
-                       goto error_release;
+                       goto err_release;
                }
        }
 
        /* request boot firmware */
-       ret = af9013_write_reg(state, 0xe205, 1);
+       ret = af9013_wr_reg(state, 0xe205, 1);
        if (ret)
-               goto error_release;
+               goto err_release;
 
        for (i = 0; i < 15; i++) {
                msleep(100);
 
                /* check firmware status */
-               ret = af9013_read_reg(state, 0x98be, &val);
+               ret = af9013_rd_reg(state, 0x98be, &val);
                if (ret)
-                       goto error_release;
+                       goto err_release;
 
-               deb_info("%s: firmware status:%02x\n", __func__, val);
+               dbg("%s: firmware status=%02x", __func__, val);
 
                if (val == 0x0c || val == 0x04) /* success or fail */
                        break;
@@ -1408,43 +1413,21 @@ static int af9013_download_firmware(struct af9013_state *state)
 
        if (val == 0x04) {
                err("firmware did not run");
-               ret = -1;
+               ret = -ENODEV;
        } else if (val != 0x0c) {
                err("firmware boot timeout");
-               ret = -1;
+               ret = -ENODEV;
        }
 
-error_release:
+err_release:
        release_firmware(fw);
-error:
+err:
 exit:
        if (!ret)
                info("found a '%s' in warm state.", af9013_ops.info.name);
        return ret;
 }
 
-static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-       int ret;
-       struct af9013_state *state = fe->demodulator_priv;
-       deb_info("%s: enable:%d\n", __func__, enable);
-
-       if (state->config.output_mode == AF9013_OUTPUT_MODE_USB)
-               ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable);
-       else
-               ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable);
-
-       return ret;
-}
-
-static void af9013_release(struct dvb_frontend *fe)
-{
-       struct af9013_state *state = fe->demodulator_priv;
-       kfree(state);
-}
-
-static struct dvb_frontend_ops af9013_ops;
-
 struct dvb_frontend *af9013_attach(const struct af9013_config *config,
        struct i2c_adapter *i2c)
 {
@@ -1455,91 +1438,65 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
        if (state == NULL)
-               goto error;
+               goto err;
 
        /* setup the state */
        state->i2c = i2c;
        memcpy(&state->config, config, sizeof(struct af9013_config));
 
        /* download firmware */
-       if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
+       if (state->config.ts_mode != AF9013_TS_USB) {
                ret = af9013_download_firmware(state);
                if (ret)
-                       goto error;
+                       goto err;
        }
 
        /* firmware version */
-       for (i = 0; i < 4; i++) {
-               ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
-       info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
-
-       /* chip version */
-       ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
+       ret = af9013_rd_regs(state, 0x5103, buf, 4);
        if (ret)
-               goto error;
-
-       /* ROM version */
-       for (i = 0; i < 2; i++) {
-               ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
-               if (ret)
-                       goto error;
-       }
-       deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
-               buf[2], buf[0], buf[1]);
+               goto err;
 
-       /* settings for mp2if */
-       if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
-               /* AF9015 split PSB to 1.5k + 0.5k */
-               ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1);
-       } else {
-               /* AF9013 change the output bit to data7 */
-               ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1);
-               if (ret)
-                       goto error;
-               /* AF9013 set mpeg to full speed */
-               ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1);
-       }
-       if (ret)
-               goto error;
-       ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1);
-       if (ret)
-               goto error;
+       info("firmware version %d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
 
        /* set GPIOs */
        for (i = 0; i < sizeof(state->config.gpio); i++) {
                ret = af9013_set_gpio(state, i, state->config.gpio[i]);
                if (ret)
-                       goto error;
+                       goto err;
        }
 
        /* create dvb_frontend */
-       memcpy(&state->frontend.ops, &af9013_ops,
+       memcpy(&state->fe.ops, &af9013_ops,
                sizeof(struct dvb_frontend_ops));
-       state->frontend.demodulator_priv = state;
+       state->fe.demodulator_priv = state;
+
+       INIT_DELAYED_WORK(&state->statistics_work, af9013_statistics_work);
 
-       return &state->frontend;
-error:
+       return &state->fe;
+err:
        kfree(state);
        return NULL;
 }
 EXPORT_SYMBOL(af9013_attach);
 
 static struct dvb_frontend_ops af9013_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
-               .name = "Afatech AF9013 DVB-T",
-               .type = FE_OFDM,
+               .name = "Afatech AF9013",
                .frequency_min = 174000000,
                .frequency_max = 862000000,
                .frequency_stepsize = 250000,
                .frequency_tolerance = 0,
-               .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 |
+               .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_TRANSMISSION_MODE_AUTO |
                        FE_CAN_GUARD_INTERVAL_AUTO |
                        FE_CAN_HIERARCHY_AUTO |
@@ -1548,24 +1505,22 @@ static struct dvb_frontend_ops af9013_ops = {
        },
 
        .release = af9013_release,
+
        .init = af9013_init,
        .sleep = af9013_sleep,
-       .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
 
+       .get_tune_settings = af9013_get_tune_settings,
        .set_frontend = af9013_set_frontend,
        .get_frontend = af9013_get_frontend,
 
-       .get_tune_settings = af9013_get_tune_settings,
-
        .read_status = af9013_read_status,
-       .read_ber = af9013_read_ber,
-       .read_signal_strength = af9013_read_signal_strength,
        .read_snr = af9013_read_snr,
+       .read_signal_strength = af9013_read_signal_strength,
+       .read_ber = af9013_read_ber,
        .read_ucblocks = af9013_read_ucblocks,
-};
 
-module_param_named(debug, af9013_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+       .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+};
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
index e53d873f75557e273735179be49e968ad2fc44c9..b973fc5a03844d68db01ee8ed2743192688b9263 100644 (file)
@@ -2,6 +2,7 @@
  * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
  *
  * Thanks to Afatech who kindly provided information.
  *
  *
  */
 
-#ifndef _AF9013_H_
-#define _AF9013_H_
+#ifndef AF9013_H
+#define AF9013_H
 
 #include <linux/dvb/frontend.h>
 
-enum af9013_ts_mode {
-       AF9013_OUTPUT_MODE_PARALLEL,
-       AF9013_OUTPUT_MODE_SERIAL,
-       AF9013_OUTPUT_MODE_USB, /* only for AF9015 */
-};
-
-enum af9013_tuner {
-       AF9013_TUNER_MXL5003D   =   3, /* MaxLinear */
-       AF9013_TUNER_MXL5005D   =  13, /* MaxLinear */
-       AF9013_TUNER_MXL5005R   =  30, /* MaxLinear */
-       AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */
-       AF9013_TUNER_MT2060     = 130, /* Microtune */
-       AF9013_TUNER_MC44S803   = 133, /* Freescale */
-       AF9013_TUNER_QT1010     = 134, /* Quantek */
-       AF9013_TUNER_UNKNOWN    = 140, /* for can tuners ? */
-       AF9013_TUNER_MT2060_2   = 147, /* Microtune */
-       AF9013_TUNER_TDA18271   = 156, /* NXP */
-       AF9013_TUNER_QT1010A    = 162, /* Quantek */
-       AF9013_TUNER_MXL5007T   = 177, /* MaxLinear */
-       AF9013_TUNER_TDA18218   = 179, /* NXP */
-};
-
 /* AF9013/5 GPIOs (mostly guessed)
    demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
    demod#1-gpio#1 - xtal setting (?)
@@ -55,44 +34,74 @@ enum af9013_tuner {
    demod#2-gpio#0 - tuner#2
    demod#2-gpio#1 - xtal setting (?)
 */
+
+struct af9013_config {
+       /*
+        * I2C address
+        */
+       u8 i2c_addr;
+
+       /*
+        * clock
+        * 20480000, 25000000, 28000000, 28800000
+        */
+       u32 clock;
+
+       /*
+        * tuner
+        */
+#define AF9013_TUNER_MXL5003D      3 /* MaxLinear */
+#define AF9013_TUNER_MXL5005D     13 /* MaxLinear */
+#define AF9013_TUNER_MXL5005R     30 /* MaxLinear */
+#define AF9013_TUNER_ENV77H11D5  129 /* Panasonic */
+#define AF9013_TUNER_MT2060      130 /* Microtune */
+#define AF9013_TUNER_MC44S803    133 /* Freescale */
+#define AF9013_TUNER_QT1010      134 /* Quantek */
+#define AF9013_TUNER_UNKNOWN     140 /* for can tuners ? */
+#define AF9013_TUNER_MT2060_2    147 /* Microtune */
+#define AF9013_TUNER_TDA18271    156 /* NXP */
+#define AF9013_TUNER_QT1010A     162 /* Quantek */
+#define AF9013_TUNER_MXL5007T    177 /* MaxLinear */
+#define AF9013_TUNER_TDA18218    179 /* NXP */
+       u8 tuner;
+
+       /*
+        * IF frequency
+        */
+       u32 if_frequency;
+
+       /*
+        * TS settings
+        */
+#define AF9013_TS_USB       0
+#define AF9013_TS_PARALLEL  1
+#define AF9013_TS_SERIAL    2
+       u8 ts_mode:2;
+
+       /*
+        * input spectrum inversion
+        */
+       bool spec_inv;
+
+       /*
+        * firmware API version
+        */
+       u8 api_version[4];
+
+       /*
+        * GPIOs
+        */
 #define AF9013_GPIO_ON (1 << 0)
 #define AF9013_GPIO_EN (1 << 1)
 #define AF9013_GPIO_O  (1 << 2)
 #define AF9013_GPIO_I  (1 << 3)
-
 #define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
 #define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-
 #define AF9013_GPIO_TUNER_ON  (AF9013_GPIO_ON|AF9013_GPIO_EN)
 #define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-
-struct af9013_config {
-       /* demodulator's I2C address */
-       u8 demod_address;
-
-       /* frequencies in kHz */
-       u32 adc_clock;
-
-       /* tuner ID */
-       u8 tuner;
-
-       /* tuner IF */
-       u16 tuner_if;
-
-       /* TS data output mode */
-       u8 output_mode:2;
-
-       /* RF spectrum inversion */
-       u8 rf_spec_inv:1;
-
-       /* API version */
-       u8 api_version[4];
-
-       /* GPIOs */
        u8 gpio[4];
 };
 
-
 #if defined(CONFIG_DVB_AF9013) || \
        (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
 extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
@@ -106,4 +115,4 @@ const struct af9013_config *config, struct i2c_adapter *i2c)
 }
 #endif /* CONFIG_DVB_AF9013 */
 
-#endif /* _AF9013_H_ */
+#endif /* AF9013_H */
index e00b2a4a2db6503a190a430066c7156c71fe3959..fa848af6e9b403fe6b8c7d9eec07d9b06647776b 100644 (file)
@@ -2,6 +2,7 @@
  * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
  *
  * Thanks to Afatech who kindly provided information.
  *
  *
  */
 
-#ifndef _AF9013_PRIV_
-#define _AF9013_PRIV_
+#ifndef AF9013_PRIV_H
+#define AF9013_PRIV_H
 
-#define LOG_PREFIX "af9013"
-extern int af9013_debug;
-
-#define dprintk(var, level, args...) \
-           do { if ((var & level)) printk(args); } while (0)
+#include "dvb_frontend.h"
+#include "af9013.h"
+#include <linux/firmware.h>
 
-#define debug_dump(b, l, func) {\
-       int loop_; \
-       for (loop_ = 0; loop_ < l; loop_++) \
-               func("%02x ", b[loop_]); \
-       func("\n");\
-}
-
-#define deb_info(args...) dprintk(af9013_debug, 0x01, args)
+#define LOG_PREFIX "af9013"
 
+#undef dbg
+#define dbg(f, arg...) \
+       if (af9013_debug) \
+               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
 #undef err
 #define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
 #undef info
@@ -48,70 +44,71 @@ extern int af9013_debug;
 
 #define AF9013_DEFAULT_FIRMWARE     "dvb-fe-af9013.fw"
 
-struct regdesc {
+struct af9013_reg_bit {
        u16 addr;
        u8  pos:4;
        u8  len:4;
        u8  val;
 };
 
-struct snr_table {
+struct af9013_snr {
        u32 val;
        u8 snr;
 };
 
-struct coeff {
-       u32 adc_clock;
-       fe_bandwidth_t bw;
+struct af9013_coeff {
+       u32 clock;
+       u32 bandwidth_hz;
        u8 val[24];
 };
 
 /* pre-calculated coeff lookup table */
-static struct coeff coeff_table[] = {
+static const struct af9013_coeff coeff_lut[] = {
        /* 28.800 MHz */
-       { 28800, BANDWIDTH_8_MHZ, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
+       { 28800000, 8000000, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
                0x51, 0x11, 0x00, 0xa2, 0x8f, 0x3d, 0x00, 0xa2, 0x8a,
                0x29, 0x00, 0xa2, 0x85, 0x14, 0x01, 0x45, 0x14, 0x14 } },
-       { 28800, BANDWIDTH_7_MHZ, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
+       { 28800000, 7000000, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
                0xc7, 0x07, 0x00, 0x8e, 0x3d, 0x55, 0x00, 0x8e, 0x38,
                0xe4, 0x00, 0x8e, 0x34, 0x72, 0x01, 0x1c, 0x71, 0x32 } },
-       { 28800, BANDWIDTH_6_MHZ, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
+       { 28800000, 6000000, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
                0x3c, 0x3d, 0x00, 0x79, 0xeb, 0x6e, 0x00, 0x79, 0xe7,
                0x9e, 0x00, 0x79, 0xe3, 0xcf, 0x00, 0xf3, 0xcf, 0x0f } },
        /* 20.480 MHz */
-       { 20480, BANDWIDTH_8_MHZ, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
+       { 20480000, 8000000, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
                0x92, 0x13, 0x00, 0xe4, 0x99, 0x6e, 0x00, 0xe4, 0x92,
                0x49, 0x00, 0xe4, 0x8b, 0x25, 0x01, 0xc9, 0x24, 0x25 } },
-       { 20480, BANDWIDTH_7_MHZ, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
+       { 20480000, 7000000, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
                0x00, 0x00, 0x00, 0xc8, 0x06, 0x40, 0x00, 0xc8, 0x00,
                0x00, 0x00, 0xc7, 0xf9, 0xc0, 0x01, 0x90, 0x00, 0x00 } },
-       { 20480, BANDWIDTH_6_MHZ, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
+       { 20480000, 6000000, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
                0x6d, 0x2e, 0x00, 0xab, 0x73, 0x13, 0x00, 0xab, 0x6d,
                0xb7, 0x00, 0xab, 0x68, 0x5c, 0x01, 0x56, 0xdb, 0x1c } },
        /* 28.000 MHz */
-       { 28000, BANDWIDTH_8_MHZ, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
+       { 28000000, 8000000, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
                0x78, 0x0a, 0x00, 0xa7, 0x34, 0x3f, 0x00, 0xa7, 0x2f,
                0x05, 0x00, 0xa7, 0x29, 0xcc, 0x01, 0x4e, 0x5e, 0x03 } },
-       { 28000, BANDWIDTH_7_MHZ, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
+       { 28000000, 7000000, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
                0x49, 0x09, 0x00, 0x92, 0x4d, 0xb7, 0x00, 0x92, 0x49,
                0x25, 0x00, 0x92, 0x44, 0x92, 0x01, 0x24, 0x92, 0x12 } },
-       { 28000, BANDWIDTH_6_MHZ, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
+       { 28000000, 6000000, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
                0x1a, 0x08, 0x00, 0x7d, 0x67, 0x2f, 0x00, 0x7d, 0x63,
                0x44, 0x00, 0x7d, 0x5f, 0x59, 0x00, 0xfa, 0xc6, 0x22 } },
        /* 25.000 MHz */
-       { 25000, BANDWIDTH_8_MHZ, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
+       { 25000000, 8000000, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
                0xf7, 0x0e, 0x00, 0xbb, 0x44, 0xc1, 0x00, 0xbb, 0x3e,
                0xe7, 0x00, 0xbb, 0x39, 0x0d, 0x01, 0x76, 0x7d, 0x34 } },
-       { 25000, BANDWIDTH_7_MHZ, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
+       { 25000000, 7000000, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
                0xb8, 0x14, 0x00, 0xa3, 0xdc, 0x29, 0x00, 0xa3, 0xd7,
                0x0a, 0x00, 0xa3, 0xd1, 0xec, 0x01, 0x47, 0xae, 0x05 } },
-       { 25000, BANDWIDTH_6_MHZ, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
+       { 25000000, 6000000, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
                0x79, 0x1b, 0x00, 0x8c, 0x73, 0x91, 0x00, 0x8c, 0x6f,
                0x2d, 0x00, 0x8c, 0x6a, 0xca, 0x01, 0x18, 0xde, 0x17 } },
 };
 
 /* QPSK SNR lookup table */
-static struct snr_table qpsk_snr_table[] = {
+static const struct af9013_snr qpsk_snr_lut[] = {
+       { 0x000000,  0 },
        { 0x0b4771,  0 },
        { 0x0c1aed,  1 },
        { 0x0d0d27,  2 },
@@ -131,7 +128,8 @@ static struct snr_table qpsk_snr_table[] = {
 };
 
 /* QAM16 SNR lookup table */
-static struct snr_table qam16_snr_table[] = {
+static const struct af9013_snr qam16_snr_lut[] = {
+       { 0x000000,  0 },
        { 0x05eb62,  5 },
        { 0x05fecf,  6 },
        { 0x060b80,  7 },
@@ -151,7 +149,8 @@ static struct snr_table qam16_snr_table[] = {
 };
 
 /* QAM64 SNR lookup table */
-static struct snr_table qam64_snr_table[] = {
+static const struct af9013_snr qam64_snr_lut[] = {
+       { 0x000000,  0 },
        { 0x03109b, 12 },
        { 0x0310d4, 13 },
        { 0x031920, 14 },
@@ -170,7 +169,7 @@ static struct snr_table qam64_snr_table[] = {
        { 0xffffff, 27 },
 };
 
-static struct regdesc ofsm_init[] = {
+static const struct af9013_reg_bit ofsm_init[] = {
        { 0xd73a, 0, 8, 0xa1 },
        { 0xd73b, 0, 8, 0x1f },
        { 0xd73c, 4, 4, 0x0a },
@@ -252,7 +251,7 @@ static struct regdesc ofsm_init[] = {
 
 /* Panasonic ENV77H11D5 tuner init
    AF9013_TUNER_ENV77H11D5 = 129 */
-static struct regdesc tuner_init_env77h11d5[] = {
+static const struct af9013_reg_bit tuner_init_env77h11d5[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x03 },
        { 0x9bbe, 0, 8, 0x01 },
@@ -318,7 +317,7 @@ static struct regdesc tuner_init_env77h11d5[] = {
 
 /* Microtune MT2060 tuner init
    AF9013_TUNER_MT2060     = 130 */
-static struct regdesc tuner_init_mt2060[] = {
+static const struct af9013_reg_bit tuner_init_mt2060[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x07 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -395,7 +394,7 @@ static struct regdesc tuner_init_mt2060[] = {
 
 /* Microtune MT2060 tuner init
    AF9013_TUNER_MT2060_2   = 147 */
-static struct regdesc tuner_init_mt2060_2[] = {
+static const struct af9013_reg_bit tuner_init_mt2060_2[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x06 },
        { 0x9bbe, 0, 8, 0x01 },
@@ -462,7 +461,7 @@ static struct regdesc tuner_init_mt2060_2[] = {
 
 /* MaxLinear MXL5003 tuner init
    AF9013_TUNER_MXL5003D   =   3 */
-static struct regdesc tuner_init_mxl5003d[] = {
+static const struct af9013_reg_bit tuner_init_mxl5003d[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x09 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -534,7 +533,7 @@ static struct regdesc tuner_init_mxl5003d[] = {
    AF9013_TUNER_MXL5005D   =  13
    AF9013_TUNER_MXL5005R   =  30
    AF9013_TUNER_MXL5007T   = 177 */
-static struct regdesc tuner_init_mxl5005[] = {
+static const struct af9013_reg_bit tuner_init_mxl5005[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x07 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -613,7 +612,7 @@ static struct regdesc tuner_init_mxl5005[] = {
 /* Quantek QT1010 tuner init
    AF9013_TUNER_QT1010     = 134
    AF9013_TUNER_QT1010A    = 162 */
-static struct regdesc tuner_init_qt1010[] = {
+static const struct af9013_reg_bit tuner_init_qt1010[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x09 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -690,7 +689,7 @@ static struct regdesc tuner_init_qt1010[] = {
 
 /* Freescale MC44S803 tuner init
    AF9013_TUNER_MC44S803   = 133 */
-static struct regdesc tuner_init_mc44s803[] = {
+static const struct af9013_reg_bit tuner_init_mc44s803[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x06 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -772,7 +771,7 @@ static struct regdesc tuner_init_mc44s803[] = {
 
 /* unknown, probably for tin can tuner, tuner init
    AF9013_TUNER_UNKNOWN   = 140 */
-static struct regdesc tuner_init_unknown[] = {
+static const struct af9013_reg_bit tuner_init_unknown[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x02 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -845,7 +844,7 @@ static struct regdesc tuner_init_unknown[] = {
 /* NXP TDA18271 & TDA18218 tuner init
    AF9013_TUNER_TDA18271   = 156
    AF9013_TUNER_TDA18218   = 179 */
-static struct regdesc tuner_init_tda18271[] = {
+static const struct af9013_reg_bit tuner_init_tda18271[] = {
        { 0x9bd5, 0, 8, 0x01 },
        { 0x9bd6, 0, 8, 0x04 },
        { 0xd1a0, 1, 1, 0x01 },
@@ -920,4 +919,4 @@ static struct regdesc tuner_init_tda18271[] = {
        { 0x9bee, 0, 1, 0x01 },
 };
 
-#endif /* _AF9013_PRIV_ */
+#endif /* AF9013_PRIV_H */
index 1539ea1f81acc9abee58b96bc04c182866febb91..a2261ea2cf82a3cf148dbb5515e3add5a309756d 100644 (file)
@@ -267,8 +267,7 @@ static void atbm8830_release(struct dvb_frontend *fe)
        kfree(state);
 }
 
-static int atbm8830_set_fe(struct dvb_frontend *fe,
-                         struct dvb_frontend_parameters *fe_params)
+static int atbm8830_set_fe(struct dvb_frontend *fe)
 {
        struct atbm_state *priv = fe->demodulator_priv;
        int i;
@@ -279,7 +278,7 @@ static int atbm8830_set_fe(struct dvb_frontend *fe,
        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, fe_params);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -298,31 +297,31 @@ static int atbm8830_set_fe(struct dvb_frontend *fe,
        return 0;
 }
 
-static int atbm8830_get_fe(struct dvb_frontend *fe,
-                         struct dvb_frontend_parameters *fe_params)
+static int atbm8830_get_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        dprintk("%s\n", __func__);
 
        /* TODO: get real readings from device */
        /* inversion status */
-       fe_params->inversion = INVERSION_OFF;
+       c->inversion = INVERSION_OFF;
 
        /* bandwidth */
-       fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+       c->bandwidth_hz = 8000000;
 
-       fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
-       fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
+       c->code_rate_HP = FEC_AUTO;
+       c->code_rate_LP = FEC_AUTO;
 
-       fe_params->u.ofdm.constellation = QAM_AUTO;
+       c->modulation = QAM_AUTO;
 
        /* transmission mode */
-       fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+       c->transmission_mode = TRANSMISSION_MODE_AUTO;
 
        /* guard interval */
-       fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+       c->guard_interval = GUARD_INTERVAL_AUTO;
 
        /* hierarchy */
-       fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       c->hierarchy = HIERARCHY_NONE;
 
        return 0;
 }
@@ -429,9 +428,9 @@ static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 
 static struct dvb_frontend_ops atbm8830_ops = {
+       .delsys = { SYS_DMBTH },
        .info = {
                .name = "AltoBeam ATBM8830/8831 DMB-TH",
-               .type = FE_OFDM,
                .frequency_min = 474000000,
                .frequency_max = 858000000,
                .frequency_stepsize = 10000,
index 1d572940e243637994b302f16a56bdb5b7caa7c6..c688b95df48645682fec8c2cefbd17cb51b5271e 100644 (file)
@@ -576,19 +576,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
 }
 
 /* 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)
+static int au8522_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct au8522_state *state = fe->demodulator_priv;
        int ret = -EINVAL;
 
-       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+       dprintk("%s(frequency=%d)\n", __func__, c->frequency);
 
-       if ((state->current_frequency == p->frequency) &&
-           (state->current_modulation == p->u.vsb.modulation))
+       if ((state->current_frequency == c->frequency) &&
+           (state->current_modulation == c->modulation))
                return 0;
 
-       au8522_enable_modulation(fe, p->u.vsb.modulation);
+       au8522_enable_modulation(fe, c->modulation);
 
        /* Allow the demod to settle */
        msleep(100);
@@ -596,7 +596,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
        if (fe->ops.tuner_ops.set_params) {
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 1);
-               ret = fe->ops.tuner_ops.set_params(fe, p);
+               ret = fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -604,7 +604,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
        if (ret < 0)
                return ret;
 
-       state->current_frequency = p->frequency;
+       state->current_frequency = c->frequency;
 
        return 0;
 }
@@ -862,7 +862,36 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
 static int au8522_read_signal_strength(struct dvb_frontend *fe,
                                       u16 *signal_strength)
 {
-       return au8522_read_snr(fe, signal_strength);
+       /* borrowed from lgdt330x.c
+        *
+        * Calculate strength from SNR up to 35dB
+        * Even though the SNR can go higher than 35dB,
+        * there is some comfort factor in having a range of
+        * strong signals that can show at 100%
+        */
+       u16 snr;
+       u32 tmp;
+       int ret = au8522_read_snr(fe, &snr);
+
+       *signal_strength = 0;
+
+       if (0 == ret) {
+               /* The following calculation method was chosen
+                * purely for the sake of code re-use from the
+                * other demod drivers that use this method */
+
+               /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+               tmp = (snr * ((1 << 24) / 10));
+
+               /* Convert from 8.24 fixed-point to
+                * scale the range 0 - 35*2^24 into 0 - 65535*/
+               if (tmp >= 8960 * 0x10000)
+                       *signal_strength = 0xffff;
+               else
+                       *signal_strength = tmp / 8960;
+       }
+
+       return ret;
 }
 
 static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -882,13 +911,13 @@ 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)
+static int au8522_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct au8522_state *state = fe->demodulator_priv;
 
-       p->frequency = state->current_frequency;
-       p->u.vsb.modulation = state->current_modulation;
+       c->frequency = state->current_frequency;
+       c->modulation = state->current_modulation;
 
        return 0;
 }
@@ -981,10 +1010,9 @@ error:
 EXPORT_SYMBOL(au8522_attach);
 
 static struct dvb_frontend_ops au8522_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name                   = "Auvitek AU8522 QAM/8VSB Frontend",
-               .type                   = FE_ATSC,
                .frequency_min          = 54000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 62500,
index 8aff5868a5e1f4b814c084a93bf3185c397224bc..033cd7ad3ca2cb9d76f7bace048fdb1f72974bdd 100644 (file)
@@ -479,16 +479,16 @@ static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
        return -EINVAL;
 }
 
-static int bcm3510_set_frontend(struct dvb_frontend* fe,
-                                            struct dvb_frontend_parameters *p)
+static int bcm3510_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct bcm3510_state* st = fe->demodulator_priv;
        struct bcm3510_hab_cmd_ext_acquire cmd;
        struct bcm3510_hab_cmd_bert_control bert;
        int ret;
 
        memset(&cmd,0,sizeof(cmd));
-       switch (p->u.vsb.modulation) {
+       switch (c->modulation) {
                case QAM_256:
                        cmd.ACQUIRE0.MODE = 0x1;
                        cmd.ACQUIRE1.SYM_RATE = 0x1;
@@ -499,7 +499,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
                        cmd.ACQUIRE1.SYM_RATE = 0x2;
                        cmd.ACQUIRE1.IF_FREQ = 0x1;
                        break;
-/*             case QAM_256:
+#if 0
+               case QAM_256:
                        cmd.ACQUIRE0.MODE = 0x3;
                        break;
                case QAM_128:
@@ -513,7 +514,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
                        break;
                case QAM_16:
                        cmd.ACQUIRE0.MODE = 0x7;
-                       break;*/
+                       break;
+#endif
                case VSB_8:
                        cmd.ACQUIRE0.MODE = 0x8;
                        cmd.ACQUIRE1.SYM_RATE = 0x0;
@@ -552,7 +554,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
 
        bcm3510_bert_reset(st);
 
-       if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
+       ret = bcm3510_set_freq(st, c->frequency);
+       if (ret < 0)
                return ret;
 
        memset(&st->status1,0,sizeof(st->status1));
@@ -819,10 +822,9 @@ error:
 EXPORT_SYMBOL(bcm3510_attach);
 
 static struct dvb_frontend_ops bcm3510_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name = "Broadcom BCM3510 VSB/QAM frontend",
-               .type = FE_ATSC,
                .frequency_min =  54000000,
                .frequency_max = 803000000,
                /* stepsize is just a guess */
index 5e431ebd089b44d997490af145a567608905732e..53e4d0dbb745ccabd5001c5b0780631e547d0f78 100644 (file)
@@ -69,18 +69,19 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        int ret;
        u8 data[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
        struct i2c_adapter *i2c = fe->tuner_priv;
 
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
+       if ((p->frequency < 950000) || (p->frequency > 2150000))
                return -EINVAL;
 
-       div = params->frequency / 1000;
+       div = p->frequency / 1000;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
index c480c839b302ba2260ca49e5bcda4f4356852f1f..c2a578e1314dce5ffb4495de51c5e97277036c12 100644 (file)
@@ -101,23 +101,24 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
        struct i2c_adapter *i2c = fe->tuner_priv;
 
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
+       if ((p->frequency < 950000) || (p->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (125 - 1)) / 125;    // round correctly
+       div = (p->frequency + (125 - 1)) / 125; /* round correctly */
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
        buf[3] = 0xC4;
 
-       if (params->frequency > 1530000)
+       if (p->frequency > 1530000)
                buf[3] = 0xc0;
 
        if (fe->ops.i2c_gate_ctrl)
index 0142214b013363735ce084a8ed63871908fccd3c..f2a90f990ce330548079b7e5ce8e9b74f1a034c9 100644 (file)
@@ -121,7 +121,8 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
        }
 }
 
-static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_parameters *p)
+static int cx22700_set_tps(struct cx22700_state *state,
+                          struct dtv_frontend_properties *p)
 {
        static const u8 qam_tab [4] = { 0, 1, 0, 2 };
        static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
@@ -146,25 +147,25 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
            p->transmission_mode != TRANSMISSION_MODE_8K)
                return -EINVAL;
 
-       if (p->constellation != QPSK &&
-           p->constellation != QAM_16 &&
-           p->constellation != QAM_64)
+       if (p->modulation != QPSK &&
+           p->modulation != QAM_16 &&
+           p->modulation != QAM_64)
                return -EINVAL;
 
-       if (p->hierarchy_information < HIERARCHY_NONE ||
-           p->hierarchy_information > HIERARCHY_4)
+       if (p->hierarchy < HIERARCHY_NONE ||
+           p->hierarchy > HIERARCHY_4)
                return -EINVAL;
 
-       if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ)
+       if (p->bandwidth_hz > 8000000 || p->bandwidth_hz < 6000000)
                return -EINVAL;
 
-       if (p->bandwidth == BANDWIDTH_7_MHZ)
+       if (p->bandwidth_hz == 7000000)
                cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 | 0x10));
        else
                cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 & ~0x10));
 
-       val = qam_tab[p->constellation - QPSK];
-       val |= p->hierarchy_information - HIERARCHY_NONE;
+       val = qam_tab[p->modulation - QPSK];
+       val |= p->hierarchy - HIERARCHY_NONE;
 
        cx22700_writereg (state, 0x04, val);
 
@@ -184,7 +185,8 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
        return 0;
 }
 
-static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_parameters *p)
+static int cx22700_get_tps(struct cx22700_state *state,
+                          struct dtv_frontend_properties *p)
 {
        static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
        static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
@@ -199,14 +201,14 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
        val = cx22700_readreg (state, 0x01);
 
        if ((val & 0x7) > 4)
-               p->hierarchy_information = HIERARCHY_AUTO;
+               p->hierarchy = HIERARCHY_AUTO;
        else
-               p->hierarchy_information = HIERARCHY_NONE + (val & 0x7);
+               p->hierarchy = HIERARCHY_NONE + (val & 0x7);
 
        if (((val >> 3) & 0x3) > 2)
-               p->constellation = QAM_AUTO;
+               p->modulation = QAM_AUTO;
        else
-               p->constellation = qam_tab[(val >> 3) & 0x3];
+               p->modulation = qam_tab[(val >> 3) & 0x3];
 
        val = cx22700_readreg (state, 0x02);
 
@@ -318,33 +320,35 @@ static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22700_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct cx22700_state* state = fe->demodulator_priv;
 
        cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
        cx22700_writereg (state, 0x00, 0x00);
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       cx22700_set_inversion (state, p->inversion);
-       cx22700_set_tps (state, &p->u.ofdm);
+       cx22700_set_inversion(state, c->inversion);
+       cx22700_set_tps(state, c);
        cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
        cx22700_writereg (state, 0x00, 0x01);  /* restart acquire */
 
        return 0;
 }
 
-static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22700_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct cx22700_state* state = fe->demodulator_priv;
        u8 reg09 = cx22700_readreg (state, 0x09);
 
-       p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
-       return cx22700_get_tps (state, &p->u.ofdm);
+       c->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
+       return cx22700_get_tps(state, c);
 }
 
 static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
@@ -401,10 +405,9 @@ error:
 }
 
 static struct dvb_frontend_ops cx22700_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Conexant CX22700 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 470000000,
                .frequency_max          = 860000000,
                .frequency_stepsize     = 166667,
index 3139558148bacb1f92a972dbaff2baf27ef4f18a..faba8248508625cccc9eec3c291c51f4191031a1 100644 (file)
@@ -146,7 +146,7 @@ static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
 
 /* Retrieve the demod settings */
 static int cx22702_get_tps(struct cx22702_state *state,
-       struct dvb_ofdm_parameters *p)
+                          struct dtv_frontend_properties *p)
 {
        u8 val;
 
@@ -157,27 +157,27 @@ static int cx22702_get_tps(struct cx22702_state *state,
        val = cx22702_readreg(state, 0x01);
        switch ((val & 0x18) >> 3) {
        case 0:
-               p->constellation = QPSK;
+               p->modulation = QPSK;
                break;
        case 1:
-               p->constellation = QAM_16;
+               p->modulation = QAM_16;
                break;
        case 2:
-               p->constellation = QAM_64;
+               p->modulation = QAM_64;
                break;
        }
        switch (val & 0x07) {
        case 0:
-               p->hierarchy_information = HIERARCHY_NONE;
+               p->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               p->hierarchy_information = HIERARCHY_1;
+               p->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               p->hierarchy_information = HIERARCHY_2;
+               p->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               p->hierarchy_information = HIERARCHY_4;
+               p->hierarchy = HIERARCHY_4;
                break;
        }
 
@@ -260,14 +260,14 @@ static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        u8 val;
        struct cx22702_state *state = fe->demodulator_priv;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -277,14 +277,14 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
 
        /* set bandwidth */
        val = cx22702_readreg(state, 0x0C) & 0xcf;
-       switch (p->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (p->bandwidth_hz) {
+       case 6000000:
                val |= 0x20;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                val |= 0x10;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                break;
        default:
                dprintk("%s: invalid bandwidth\n", __func__);
@@ -292,15 +292,15 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
        }
        cx22702_writereg(state, 0x0C, val);
 
-       p->u.ofdm.code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
+       p->code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
 
        /* use auto configuration? */
-       if ((p->u.ofdm.hierarchy_information == HIERARCHY_AUTO) ||
-          (p->u.ofdm.constellation == QAM_AUTO) ||
-          (p->u.ofdm.code_rate_HP == FEC_AUTO) ||
-          (p->u.ofdm.code_rate_LP == FEC_AUTO) ||
-          (p->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO) ||
-          (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO)) {
+       if ((p->hierarchy == HIERARCHY_AUTO) ||
+          (p->modulation == QAM_AUTO) ||
+          (p->code_rate_HP == FEC_AUTO) ||
+          (p->code_rate_LP == FEC_AUTO) ||
+          (p->guard_interval == GUARD_INTERVAL_AUTO) ||
+          (p->transmission_mode == TRANSMISSION_MODE_AUTO)) {
 
                /* TPS Source - use hardware driven values */
                cx22702_writereg(state, 0x06, 0x10);
@@ -316,7 +316,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
        }
 
        /* manually programmed values */
-       switch (p->u.ofdm.constellation) {              /* mask 0x18 */
+       switch (p->modulation) {                /* mask 0x18 */
        case QPSK:
                val = 0x00;
                break;
@@ -327,10 +327,10 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
                val = 0x10;
                break;
        default:
-               dprintk("%s: invalid constellation\n", __func__);
+               dprintk("%s: invalid modulation\n", __func__);
                return -EINVAL;
        }
-       switch (p->u.ofdm.hierarchy_information) {      /* mask 0x07 */
+       switch (p->hierarchy) { /* mask 0x07 */
        case HIERARCHY_NONE:
                break;
        case HIERARCHY_1:
@@ -348,7 +348,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
        }
        cx22702_writereg(state, 0x06, val);
 
-       switch (p->u.ofdm.code_rate_HP) {               /* mask 0x38 */
+       switch (p->code_rate_HP) {              /* mask 0x38 */
        case FEC_NONE:
        case FEC_1_2:
                val = 0x00;
@@ -369,7 +369,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
                dprintk("%s: invalid code_rate_HP\n", __func__);
                return -EINVAL;
        }
-       switch (p->u.ofdm.code_rate_LP) {               /* mask 0x07 */
+       switch (p->code_rate_LP) {              /* mask 0x07 */
        case FEC_NONE:
        case FEC_1_2:
                break;
@@ -391,7 +391,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
        }
        cx22702_writereg(state, 0x07, val);
 
-       switch (p->u.ofdm.guard_interval) {             /* mask 0x0c */
+       switch (p->guard_interval) {            /* mask 0x0c */
        case GUARD_INTERVAL_1_32:
                val = 0x00;
                break;
@@ -408,7 +408,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
                dprintk("%s: invalid guard_interval\n", __func__);
                return -EINVAL;
        }
-       switch (p->u.ofdm.transmission_mode) {          /* mask 0x03 */
+       switch (p->transmission_mode) {         /* mask 0x03 */
        case TRANSMISSION_MODE_2K:
                break;
        case TRANSMISSION_MODE_8K:
@@ -546,15 +546,15 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
        return 0;
 }
 
-static int cx22702_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct cx22702_state *state = fe->demodulator_priv;
 
        u8 reg0C = cx22702_readreg(state, 0x0C);
 
-       p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
-       return cx22702_get_tps(state, &p->u.ofdm);
+       c->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
+       return cx22702_get_tps(state, c);
 }
 
 static int cx22702_get_tune_settings(struct dvb_frontend *fe,
@@ -603,10 +603,9 @@ error:
 EXPORT_SYMBOL(cx22702_attach);
 
 static const struct dvb_frontend_ops cx22702_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Conexant CX22702 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 177000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 166666,
index bf9c999aa47051d7b71420cd20be6e3f2a781589..5101f10f2d7a010cd4a2702e20ceabd0ca8eb2b7 100644 (file)
@@ -531,26 +531,27 @@ static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24110_set_frontend(struct dvb_frontend *fe)
 {
        struct cx24110_state *state = fe->demodulator_priv;
-
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       cx24110_set_inversion (state, p->inversion);
-       cx24110_set_fec (state, p->u.qpsk.fec_inner);
-       cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
+       cx24110_set_inversion(state, p->inversion);
+       cx24110_set_fec(state, p->fec_inner);
+       cx24110_set_symbolrate(state, p->symbol_rate);
        cx24110_writereg(state,0x04,0x05); /* start acquisition */
 
        return 0;
 }
 
-static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24110_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct cx24110_state *state = fe->demodulator_priv;
        s32 afc; unsigned sclk;
 
@@ -571,7 +572,7 @@ static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        p->frequency += afc;
        p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
                                INVERSION_ON : INVERSION_OFF;
-       p->u.qpsk.fec_inner = cx24110_get_fec (state);
+       p->fec_inner = cx24110_get_fec(state);
 
        return 0;
 }
@@ -623,10 +624,9 @@ error:
 }
 
 static struct dvb_frontend_ops cx24110_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name = "Conexant CX24110 DVB-S",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1011,  /* kHz for QPSK frontends */
index c341d57d5e818d9c57d34e09e790eb937f0e5475..3883c3b31aef3d98109059242b73063d8a40d468 100644 (file)
@@ -476,21 +476,21 @@ static int cx24113_init(struct dvb_frontend *fe)
        return ret;
 }
 
-static int cx24113_set_params(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *p)
+static int cx24113_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct cx24113_state *state = fe->tuner_priv;
        /* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */
        u32 roll_off = 675;
        u32 bw;
 
-       bw  = ((p->u.qpsk.symbol_rate/100) * roll_off) / 1000;
+       bw  = ((c->symbol_rate/100) * roll_off) / 1000;
        bw += (10000000/100) + 5;
        bw /= 10;
        bw += 1000;
        cx24113_set_bandwidth(state, bw);
 
-       cx24113_set_frequency(state, p->frequency);
+       cx24113_set_frequency(state, c->frequency);
        msleep(5);
        return cx24113_get_status(fe, &bw);
 }
@@ -547,11 +547,9 @@ static const struct dvb_tuner_ops cx24113_tuner_ops = {
        .release       = cx24113_release,
 
        .init          = cx24113_init,
-       .sleep         = NULL,
 
        .set_params    = cx24113_set_params,
        .get_frequency = cx24113_get_frequency,
-       .get_bandwidth = NULL,
        .get_status    = cx24113_get_status,
 };
 
index ccd05255d52730225530580b6bedec2a8df99336..b4887918653719740f34398e762e604869000c05 100644 (file)
@@ -1212,25 +1212,10 @@ static int cx24116_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int cx24116_set_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
-static int cx24116_get_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
 /* dvb-core told us to tune, the tv property cache will be complete,
  * it's safe for is to pull values and use them for tuning purposes.
  */
-static int cx24116_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx24116_set_frontend(struct dvb_frontend *fe)
 {
        struct cx24116_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1455,12 +1440,20 @@ tuned:  /* Set/Reset B/W */
        return cx24116_cmd_execute(fe, &cmd);
 }
 
-static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
+static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
        unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
 {
+       /*
+        * It is safe to discard "params" here, as the DVB core will sync
+        * fe->dtv_property_cache with fepriv->parameters_in, where the
+        * DVBv3 params are stored. The only practical usage for it indicate
+        * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
+        * true.
+        */
+
        *delay = HZ / 5;
-       if (params) {
-               int ret = cx24116_set_frontend(fe, params);
+       if (re_tune) {
+               int ret = cx24116_set_frontend(fe);
                if (ret)
                        return ret;
        }
@@ -1473,10 +1466,9 @@ static int cx24116_get_algo(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops cx24116_ops = {
-
+       .delsys = { SYS_DVBS, SYS_DVBS2 },
        .info = {
                .name = "Conexant CX24116/CX24118",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1011, /* kHz for QPSK frontends */
@@ -1507,8 +1499,6 @@ static struct dvb_frontend_ops cx24116_ops = {
        .get_frontend_algo = cx24116_get_algo,
        .tune = cx24116_tune,
 
-       .set_property = cx24116_set_property,
-       .get_property = cx24116_get_property,
        .set_frontend = cx24116_set_frontend,
 };
 
index b1dd8acc607a4d70133524501f643e3deb89f081..7e28b4ee7d4febb9f815ea569fbfc14f38764b6a 100644 (file)
@@ -526,9 +526,9 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
  * to be configured and the correct band selected.
  * Calculate those values.
  */
-static int cx24123_pll_calculate(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct cx24123_state *state = fe->demodulator_priv;
        u32 ndiv = 0, adiv = 0, vco_div = 0;
        int i = 0;
@@ -548,8 +548,8 @@ static int cx24123_pll_calculate(struct dvb_frontend *fe,
         * FILTUNE programming bits */
        for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
                agcv = &cx24123_AGC_vals[i];
-               if ((agcv->symbolrate_low <= p->u.qpsk.symbol_rate) &&
-                   (agcv->symbolrate_high >= p->u.qpsk.symbol_rate)) {
+               if ((agcv->symbolrate_low <= p->symbol_rate) &&
+                   (agcv->symbolrate_high >= p->symbol_rate)) {
                        state->VCAarg = agcv->VCAprogdata;
                        state->VGAarg = agcv->VGAprogdata;
                        state->FILTune = agcv->FILTune;
@@ -601,8 +601,7 @@ static int cx24123_pll_calculate(struct dvb_frontend *fe,
  * Tuner cx24109 is written through a dedicated 3wire interface
  * on the demod chip.
  */
-static int cx24123_pll_writereg(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend *fe, u32 data)
 {
        struct cx24123_state *state = fe->demodulator_priv;
        unsigned long timeout;
@@ -659,26 +658,26 @@ static int cx24123_pll_writereg(struct dvb_frontend *fe,
        return 0;
 }
 
-static int cx24123_pll_tune(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct cx24123_state *state = fe->demodulator_priv;
        u8 val;
 
        dprintk("frequency=%i\n", p->frequency);
 
-       if (cx24123_pll_calculate(fe, p) != 0) {
+       if (cx24123_pll_calculate(fe) != 0) {
                err("%s: cx24123_pll_calcutate failed\n", __func__);
                return -EINVAL;
        }
 
        /* Write the new VCO/VGA */
-       cx24123_pll_writereg(fe, p, state->VCAarg);
-       cx24123_pll_writereg(fe, p, state->VGAarg);
+       cx24123_pll_writereg(fe, state->VCAarg);
+       cx24123_pll_writereg(fe, state->VGAarg);
 
        /* Write the new bandselect and pll args */
-       cx24123_pll_writereg(fe, p, state->bandselectarg);
-       cx24123_pll_writereg(fe, p, state->pllarg);
+       cx24123_pll_writereg(fe, state->bandselectarg);
+       cx24123_pll_writereg(fe, state->pllarg);
 
        /* set the FILTUNE voltage */
        val = cx24123_readreg(state, 0x28) & ~0x3;
@@ -925,10 +924,10 @@ static int cx24123_read_snr(struct dvb_frontend *fe, u16 *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 cx24123_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
        dprintk("\n");
 
@@ -936,16 +935,16 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
                state->config->set_ts_params(fe, 0);
 
        state->currentfreq = p->frequency;
-       state->currentsymbolrate = p->u.qpsk.symbol_rate;
+       state->currentsymbolrate = p->symbol_rate;
 
        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_set_fec(state, p->fec_inner);
+       cx24123_set_symbolrate(state, p->symbol_rate);
 
        if (!state->config->dont_use_pll)
-               cx24123_pll_tune(fe, p);
+               cx24123_pll_tune(fe);
        else if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
        else
                err("it seems I don't have a tuner...");
 
@@ -960,9 +959,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
        return 0;
 }
 
-static int cx24123_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cx24123_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct cx24123_state *state = fe->demodulator_priv;
 
        dprintk("\n");
@@ -971,12 +970,12 @@ static int cx24123_get_frontend(struct dvb_frontend *fe,
                err("%s: Failed to get inversion status\n", __func__);
                return -EREMOTEIO;
        }
-       if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+       if (cx24123_get_fec(state, &p->fec_inner) != 0) {
                err("%s: Failed to get fec status\n", __func__);
                return -EREMOTEIO;
        }
        p->frequency = state->currentfreq;
-       p->u.qpsk.symbol_rate = state->currentsymbolrate;
+       p->symbol_rate = state->currentsymbolrate;
 
        return 0;
 }
@@ -1007,15 +1006,15 @@ static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 }
 
 static int cx24123_tune(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *params,
+                       bool re_tune,
                        unsigned int mode_flags,
                        unsigned int *delay,
                        fe_status_t *status)
 {
        int retval = 0;
 
-       if (params != NULL)
-               retval = cx24123_set_frontend(fe, params);
+       if (re_tune)
+               retval = cx24123_set_frontend(fe);
 
        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
                cx24123_read_status(fe, status);
@@ -1126,10 +1125,9 @@ error:
 EXPORT_SYMBOL(cx24123_attach);
 
 static struct dvb_frontend_ops cx24123_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name = "Conexant CX24123/CX24109",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1011, /* kHz for QPSK frontends */
index 03cab7b547fbac253331206de193848acc8b93a0..cf0f546aa1d1bdf94f47666692c0313cf69d6643 100644 (file)
@@ -63,19 +63,6 @@ struct cxd2820r_config {
         */
        bool spec_inv;
 
-       /* IFs for all used modes.
-        * Default: none, must set
-        * Values: <kHz>
-        */
-       u16 if_dvbt_6;
-       u16 if_dvbt_7;
-       u16 if_dvbt_8;
-       u16 if_dvbt2_5;
-       u16 if_dvbt2_6;
-       u16 if_dvbt2_7;
-       u16 if_dvbt2_8;
-       u16 if_dvbc;
-
        /* GPIOs for all used modes.
         * Default: none, disabled
         * Values: <see above>
index b85f5011e344623fc3a03fbfb10d09d8df59a54f..945404991529d1517a046281d807b23385aed6c3 100644 (file)
 
 #include "cxd2820r_priv.h"
 
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret, i;
        u8 buf[2];
+       u32 if_freq;
        u16 if_ctl;
        u64 num;
        struct reg_val_mask tab[] = {
@@ -56,9 +56,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, params);
+               fe->ops.tuner_ops.set_params(fe);
 
-       if (priv->delivery_system !=  SYS_DVBC_ANNEX_AC) {
+       if (priv->delivery_system !=  SYS_DVBC_ANNEX_A) {
                for (i = 0; i < ARRAY_SIZE(tab); i++) {
                        ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
                                tab[i].val, tab[i].mask);
@@ -67,10 +67,20 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
                }
        }
 
-       priv->delivery_system = SYS_DVBC_ANNEX_AC;
+       priv->delivery_system = SYS_DVBC_ANNEX_A;
        priv->ber_running = 0; /* tune stops BER counter */
 
-       num = priv->cfg.if_dvbc;
+       /* program IF frequency */
+       if (fe->ops.tuner_ops.get_if_frequency) {
+               ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+               if (ret)
+                       goto error;
+       } else
+               if_freq = 0;
+
+       dbg("%s: if_freq=%d", __func__, if_freq);
+
+       num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
        if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = (if_ctl >> 8) & 0x3f;
@@ -94,8 +104,7 @@ error:
        return ret;
 }
 
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
index 036480f967b7b73c21a42004e17e1a8d2bc018ef..93e1b12e79077ddc851ffd5fd85c8240c795eed7 100644 (file)
@@ -240,422 +240,234 @@ error:
        return ret;
 }
 
-/* lock FE */
-static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)
-{
-       int ret = 0;
-       dbg("%s: active_fe=%d", __func__, active_fe);
-
-       mutex_lock(&priv->fe_lock);
-
-       /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
-       if (priv->active_fe == active_fe)
-               ;
-       else if (priv->active_fe == -1)
-               priv->active_fe = active_fe;
-       else
-               ret = -EBUSY;
-
-       mutex_unlock(&priv->fe_lock);
-
-       return ret;
-}
-
-/* unlock FE */
-static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)
-{
-       dbg("%s: active_fe=%d", __func__, active_fe);
-
-       mutex_lock(&priv->fe_lock);
-
-       /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
-       if (priv->active_fe == active_fe)
-               priv->active_fe = -1;
-
-       mutex_unlock(&priv->fe_lock);
-
-       return;
-}
-
 /* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
 u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
 {
        return div_u64(dividend + (divisor / 2), divisor);
 }
 
-static int cxd2820r_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cxd2820r_set_frontend(struct dvb_frontend *fe)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (priv->delivery_system) {
-               case SYS_UNDEFINED:
-                       if (c->delivery_system == SYS_DVBT) {
-                               /* SLEEP => DVB-T */
-                               ret = cxd2820r_set_frontend_t(fe, p);
-                       } else {
-                               /* SLEEP => DVB-T2 */
-                               ret = cxd2820r_set_frontend_t2(fe, p);
-                       }
-                       break;
-               case SYS_DVBT:
-                       if (c->delivery_system == SYS_DVBT) {
-                               /* DVB-T => DVB-T */
-                               ret = cxd2820r_set_frontend_t(fe, p);
-                       } else if (c->delivery_system == SYS_DVBT2) {
-                               /* DVB-T => DVB-T2 */
-                               ret = cxd2820r_sleep_t(fe);
-                               if (ret)
-                                       break;
-                               ret = cxd2820r_set_frontend_t2(fe, p);
-                       }
-                       break;
-               case SYS_DVBT2:
-                       if (c->delivery_system == SYS_DVBT2) {
-                               /* DVB-T2 => DVB-T2 */
-                               ret = cxd2820r_set_frontend_t2(fe, p);
-                       } else if (c->delivery_system == SYS_DVBT) {
-                               /* DVB-T2 => DVB-T */
-                               ret = cxd2820r_sleep_t2(fe);
-                               if (ret)
-                                       break;
-                               ret = cxd2820r_set_frontend_t(fe, p);
-                       }
-                       break;
-               default:
-                       dbg("%s: error state=%d", __func__,
-                               priv->delivery_system);
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
-
-               ret = cxd2820r_set_frontend_c(fe, p);
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (c->delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_init_t(fe);
+               if (ret < 0)
+                       goto err;
+               ret = cxd2820r_set_frontend_t(fe);
+               if (ret < 0)
+                       goto err;
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_init_t(fe);
+               if (ret < 0)
+                       goto err;
+               ret = cxd2820r_set_frontend_t2(fe);
+               if (ret < 0)
+                       goto err;
+               break;
+       case SYS_DVBC_ANNEX_A:
+               ret = cxd2820r_init_c(fe);
+               if (ret < 0)
+                       goto err;
+               ret = cxd2820r_set_frontend_c(fe);
+               if (ret < 0)
+                       goto err;
+               break;
+       default:
+               dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system);
+               ret = -EINVAL;
+               break;
        }
-
+err:
        return ret;
 }
-
 static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_read_status_t(fe, status);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_read_status_t2(fe, status);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_read_status_t(fe, status);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_read_status_t2(fe, status);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_read_status_c(fe, status);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
-static int cxd2820r_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int cxd2820r_get_frontend(struct dvb_frontend *fe)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_get_frontend_t(fe, p);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_get_frontend_t2(fe, p);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
-
-               ret = cxd2820r_get_frontend_c(fe, p);
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_get_frontend_t(fe);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_get_frontend_t2(fe);
+               break;
+       case SYS_DVBC_ANNEX_A:
+               ret = cxd2820r_get_frontend_c(fe);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_read_ber_t(fe, ber);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_read_ber_t2(fe, ber);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_read_ber_t(fe, ber);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_read_ber_t2(fe, ber);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_read_ber_c(fe, ber);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_read_signal_strength_t(fe, strength);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_read_signal_strength_t2(fe, strength);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_read_signal_strength_t(fe, strength);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_read_signal_strength_t2(fe, strength);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_read_signal_strength_c(fe, strength);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_read_snr_t(fe, snr);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_read_snr_t2(fe, snr);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_read_snr_t(fe, snr);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_read_snr_t2(fe, snr);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_read_snr_c(fe, snr);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_init(struct dvb_frontend *fe)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
-       int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       priv->delivery_system = SYS_UNDEFINED;
-       /* delivery system is unknown at that (init) phase */
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               ret = cxd2820r_init_t(fe);
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
-
-               ret = cxd2820r_init_c(fe);
-       }
-
-       return ret;
+       return 0;
 }
 
 static int cxd2820r_sleep(struct dvb_frontend *fe)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_sleep_t(fe);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_sleep_t2(fe);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-
-               cxd2820r_unlock(priv, 0);
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_sleep_t(fe);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_sleep_t2(fe);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_sleep_c(fe);
-
-               cxd2820r_unlock(priv, 1);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
 static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
-       struct dvb_frontend_tune_settings *s)
+                                     struct dvb_frontend_tune_settings *s)
 {
-       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-       if (fe->ops.info.type == FE_OFDM) {
-               /* DVB-T/T2 */
-               ret = cxd2820r_lock(priv, 0);
-               if (ret)
-                       return ret;
-
-               switch (fe->dtv_property_cache.delivery_system) {
-               case SYS_DVBT:
-                       ret = cxd2820r_get_tune_settings_t(fe, s);
-                       break;
-               case SYS_DVBT2:
-                       ret = cxd2820r_get_tune_settings_t2(fe, s);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-       } else {
-               /* DVB-C */
-               ret = cxd2820r_lock(priv, 1);
-               if (ret)
-                       return ret;
 
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       switch (fe->dtv_property_cache.delivery_system) {
+       case SYS_DVBT:
+               ret = cxd2820r_get_tune_settings_t(fe, s);
+               break;
+       case SYS_DVBT2:
+               ret = cxd2820r_get_tune_settings_t2(fe, s);
+               break;
+       case SYS_DVBC_ANNEX_A:
                ret = cxd2820r_get_tune_settings_c(fe, s);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
-
        return ret;
 }
 
-static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -664,7 +476,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
        /* switch between DVB-T and DVB-T2 when tune fails */
-       if (priv->last_tune_failed) {
+       if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) {
                if (priv->delivery_system == SYS_DVBT)
                        c->delivery_system = SYS_DVBT2;
                else
@@ -672,7 +484,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
        }
 
        /* set frontend */
-       ret = cxd2820r_set_frontend(fe, p);
+       ret = cxd2820r_set_frontend(fe);
        if (ret)
                goto error;
 
@@ -727,9 +539,7 @@ static void cxd2820r_release(struct dvb_frontend *fe)
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        dbg("%s", __func__);
 
-       if (fe->ops.info.type == FE_OFDM)
-               kfree(priv);
-
+       kfree(priv);
        return;
 }
 
@@ -742,128 +552,79 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
 }
 
-static const struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops = {
+       .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
+       /* default: DVB-T/T2 */
+       .info = {
+               .name = "Sony CXD2820R (DVB-T/T2)",
+
+               .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_256                  |
+                       FE_CAN_QAM_AUTO                 |
+                       FE_CAN_TRANSMISSION_MODE_AUTO   |
+                       FE_CAN_GUARD_INTERVAL_AUTO      |
+                       FE_CAN_HIERARCHY_AUTO           |
+                       FE_CAN_MUTE_TS                  |
+                       FE_CAN_2G_MODULATION
+               },
 
-struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
-       struct i2c_adapter *i2c, struct dvb_frontend *fe)
-{
-       int ret;
-       struct cxd2820r_priv *priv = NULL;
-       u8 tmp;
+       .release                = cxd2820r_release,
+       .init                   = cxd2820r_init,
+       .sleep                  = cxd2820r_sleep,
 
-       if (fe == NULL) {
-               /* FE0 */
-               /* allocate memory for the internal priv */
-               priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
-               if (priv == NULL)
-                       goto error;
+       .get_tune_settings      = cxd2820r_get_tune_settings,
+       .i2c_gate_ctrl          = cxd2820r_i2c_gate_ctrl,
 
-               /* setup the priv */
-               priv->i2c = i2c;
-               memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
-               mutex_init(&priv->fe_lock);
+       .get_frontend           = cxd2820r_get_frontend,
 
-               priv->active_fe = -1; /* NONE */
+       .get_frontend_algo      = cxd2820r_get_frontend_algo,
+       .search                 = cxd2820r_search,
 
-               /* check if the demod is there */
-               priv->bank[0] = priv->bank[1] = 0xff;
-               ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
-               dbg("%s: chip id=%02x", __func__, tmp);
-               if (ret || tmp != 0xe1)
-                       goto error;
+       .read_status            = cxd2820r_read_status,
+       .read_snr               = cxd2820r_read_snr,
+       .read_ber               = cxd2820r_read_ber,
+       .read_ucblocks          = cxd2820r_read_ucblocks,
+       .read_signal_strength   = cxd2820r_read_signal_strength,
+};
 
-               /* create frontends */
-               memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],
-                       sizeof(struct dvb_frontend_ops));
-               memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],
-                       sizeof(struct dvb_frontend_ops));
+struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
+                                    struct i2c_adapter *i2c,
+                                    struct dvb_frontend *fe)
+{
+       struct cxd2820r_priv *priv = NULL;
+       int ret;
+       u8 tmp;
 
-               priv->fe[0].demodulator_priv = priv;
-               priv->fe[1].demodulator_priv = priv;
+       priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL);
+       if (!priv)
+               goto error;
 
-               return &priv->fe[0];
+       priv->i2c = i2c;
+       memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config));
 
-       } else {
-               /* FE1: FE0 given as pointer, just return FE1 we have
-                * already created */
-               priv = fe->demodulator_priv;
-               return &priv->fe[1];
-       }
+       priv->bank[0] = priv->bank[1] = 0xff;
+       ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
+       dbg("%s: chip id=%02x", __func__, tmp);
+       if (ret || tmp != 0xe1)
+               goto error;
 
+       memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops));
+       priv->fe.demodulator_priv = priv;
+       return &priv->fe;
 error:
        kfree(priv);
        return NULL;
 }
 EXPORT_SYMBOL(cxd2820r_attach);
 
-static const struct dvb_frontend_ops cxd2820r_ops[2] = {
-       {
-               /* DVB-T/T2 */
-               .info = {
-                       .name = "Sony CXD2820R (DVB-T/T2)",
-                       .type = FE_OFDM,
-                       .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_256 |
-                               FE_CAN_QAM_AUTO |
-                               FE_CAN_TRANSMISSION_MODE_AUTO |
-                               FE_CAN_GUARD_INTERVAL_AUTO |
-                               FE_CAN_HIERARCHY_AUTO |
-                               FE_CAN_MUTE_TS |
-                               FE_CAN_2G_MODULATION
-               },
-
-               .release = cxd2820r_release,
-               .init = cxd2820r_init,
-               .sleep = cxd2820r_sleep,
-
-               .get_tune_settings = cxd2820r_get_tune_settings,
-               .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
-
-               .get_frontend = cxd2820r_get_frontend,
-
-               .get_frontend_algo = cxd2820r_get_frontend_algo,
-               .search = cxd2820r_search,
-
-               .read_status = cxd2820r_read_status,
-               .read_snr = cxd2820r_read_snr,
-               .read_ber = cxd2820r_read_ber,
-               .read_ucblocks = cxd2820r_read_ucblocks,
-               .read_signal_strength = cxd2820r_read_signal_strength,
-       },
-       {
-               /* DVB-C */
-               .info = {
-                       .name = "Sony CXD2820R (DVB-C)",
-                       .type = FE_QAM,
-                       .caps =
-                               FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-                               FE_CAN_QAM_128 | FE_CAN_QAM_256 |
-                               FE_CAN_FEC_AUTO
-               },
-
-               .release = cxd2820r_release,
-               .init = cxd2820r_init,
-               .sleep = cxd2820r_sleep,
-
-               .get_tune_settings = cxd2820r_get_tune_settings,
-               .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
-
-               .set_frontend = cxd2820r_set_frontend,
-               .get_frontend = cxd2820r_get_frontend,
-
-               .read_status = cxd2820r_read_status,
-               .read_snr = cxd2820r_read_snr,
-               .read_ber = cxd2820r_read_ber,
-               .read_ucblocks = cxd2820r_read_ucblocks,
-               .read_signal_strength = cxd2820r_read_signal_strength,
-       },
-};
-
-
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
 MODULE_LICENSE("GPL");
index 95539134efdb796c911543b908a37390e6eb2121..9a9822cad9cd59de41dce73474c51f44fa0e802c 100644 (file)
@@ -48,12 +48,9 @@ struct reg_val_mask {
 
 struct cxd2820r_priv {
        struct i2c_adapter *i2c;
-       struct dvb_frontend fe[2];
+       struct dvb_frontend fe;
        struct cxd2820r_config cfg;
 
-       struct mutex fe_lock; /* FE lock */
-       int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
-
        bool ber_running;
 
        u8 bank[2];
@@ -89,11 +86,9 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
 
 /* cxd2820r_c.c */
 
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
 
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
 
 int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
 
@@ -114,11 +109,9 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
 
 /* cxd2820r_t.c */
 
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
 
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
 
 int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
 
@@ -139,11 +132,9 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
 
 /* cxd2820r_t2.c */
 
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
 
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);
 
 int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
 
index a04f9c810101652138b2685973c1969d3cdf9c31..1a026239cdcc081afeb2b3f6d3e172d73a4c224c 100644 (file)
 
 #include "cxd2820r_priv.h"
 
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i;
-       u32 if_khz, if_ctl;
+       int ret, i, bw_i;
+       u32 if_freq, if_ctl;
        u64 num;
        u8 buf[3], bw_param;
        u8 bw_params1[][5] = {
@@ -57,6 +56,23 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
 
        dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
 
+       switch (c->bandwidth_hz) {
+       case 6000000:
+               bw_i = 0;
+               bw_param = 2;
+               break;
+       case 7000000:
+               bw_i = 1;
+               bw_param = 1;
+               break;
+       case 8000000:
+               bw_i = 2;
+               bw_param = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* update GPIOs */
        ret = cxd2820r_gpio(fe);
        if (ret)
@@ -64,7 +80,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
 
        if (priv->delivery_system != SYS_DVBT) {
                for (i = 0; i < ARRAY_SIZE(tab); i++) {
@@ -78,27 +94,17 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
        priv->delivery_system = SYS_DVBT;
        priv->ber_running = 0; /* tune stops BER counter */
 
-       switch (c->bandwidth_hz) {
-       case 6000000:
-               if_khz = priv->cfg.if_dvbt_6;
-               i = 0;
-               bw_param = 2;
-               break;
-       case 7000000:
-               if_khz = priv->cfg.if_dvbt_7;
-               i = 1;
-               bw_param = 1;
-               break;
-       case 8000000:
-               if_khz = priv->cfg.if_dvbt_8;
-               i = 2;
-               bw_param = 0;
-               break;
-       default:
-               return -EINVAL;
-       }
+       /* program IF frequency */
+       if (fe->ops.tuner_ops.get_if_frequency) {
+               ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+               if (ret)
+                       goto error;
+       } else
+               if_freq = 0;
+
+       dbg("%s: if_freq=%d", __func__, if_freq);
 
-       num = if_khz;
+       num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
        if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = ((if_ctl >> 16) & 0xff);
@@ -109,7 +115,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
        if (ret)
                goto error;
 
-       ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5);
+       ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5);
        if (ret)
                goto error;
 
@@ -117,7 +123,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
        if (ret)
                goto error;
 
-       ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2);
+       ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2);
        if (ret)
                goto error;
 
@@ -135,8 +141,7 @@ error:
        return ret;
 }
 
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
index 6548588309f7986ffc347e7c2915cc30fef0ec9c..3a5759e0d2352c3d6753acd400bd9d32442e6cdf 100644 (file)
 
 #include "cxd2820r_priv.h"
 
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i;
-       u32 if_khz, if_ctl;
+       int ret, i, bw_i;
+       u32 if_freq, if_ctl;
        u64 num;
        u8 buf[3], bw_param;
        u8 bw_params1[][5] = {
@@ -71,6 +70,27 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
 
        dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
 
+       switch (c->bandwidth_hz) {
+       case 5000000:
+               bw_i = 0;
+               bw_param = 3;
+               break;
+       case 6000000:
+               bw_i = 1;
+               bw_param = 2;
+               break;
+       case 7000000:
+               bw_i = 2;
+               bw_param = 1;
+               break;
+       case 8000000:
+               bw_i = 3;
+               bw_param = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* update GPIOs */
        ret = cxd2820r_gpio(fe);
        if (ret)
@@ -78,7 +98,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, params);
+               fe->ops.tuner_ops.set_params(fe);
 
        if (priv->delivery_system != SYS_DVBT2) {
                for (i = 0; i < ARRAY_SIZE(tab); i++) {
@@ -91,32 +111,17 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
 
        priv->delivery_system = SYS_DVBT2;
 
-       switch (c->bandwidth_hz) {
-       case 5000000:
-               if_khz = priv->cfg.if_dvbt2_5;
-               i = 0;
-               bw_param = 3;
-               break;
-       case 6000000:
-               if_khz = priv->cfg.if_dvbt2_6;
-               i = 1;
-               bw_param = 2;
-               break;
-       case 7000000:
-               if_khz = priv->cfg.if_dvbt2_7;
-               i = 2;
-               bw_param = 1;
-               break;
-       case 8000000:
-               if_khz = priv->cfg.if_dvbt2_8;
-               i = 3;
-               bw_param = 0;
-               break;
-       default:
-               return -EINVAL;
-       }
+       /* program IF frequency */
+       if (fe->ops.tuner_ops.get_if_frequency) {
+               ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+               if (ret)
+                       goto error;
+       } else
+               if_freq = 0;
+
+       dbg("%s: if_freq=%d", __func__, if_freq);
 
-       num = if_khz;
+       num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
        if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = ((if_ctl >> 16) & 0xff);
@@ -127,7 +132,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
        if (ret)
                goto error;
 
-       ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5);
+       ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
        if (ret)
                goto error;
 
@@ -150,8 +155,7 @@ error:
 
 }
 
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
index dc1cb17a6ea716993fe5e31c187bcd1f41881838..3b024bfe980aec8ef10cc5f5ae6fb78ff647e68e 100644 (file)
@@ -150,7 +150,7 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
     } \
 } while (0)
 
-static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib0070_set_bandwidth(struct dvb_frontend *fe)
 {
     struct dib0070_state *state = fe->tuner_priv;
     u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
@@ -335,7 +335,7 @@ static const struct dib0070_lna_match dib0070_lna[] = {
 };
 
 #define LPF    100
-static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib0070_tune_digital(struct dvb_frontend *fe)
 {
     struct dib0070_state *state = fe->tuner_priv;
 
@@ -507,7 +507,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
 
        *tune_state = CT_TUNER_STEP_5;
     } else if (*tune_state == CT_TUNER_STEP_5) {
-       dib0070_set_bandwidth(fe, ch);
+       dib0070_set_bandwidth(fe);
        *tune_state = CT_TUNER_STOP;
     } else {
        ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
@@ -516,7 +516,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
 }
 
 
-static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dib0070_tune(struct dvb_frontend *fe)
 {
     struct dib0070_state *state = fe->tuner_priv;
     uint32_t ret;
@@ -524,7 +524,7 @@ static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters
     state->tune_state = CT_TUNER_START;
 
     do {
-       ret = dib0070_tune_digital(fe, p);
+       ret = dib0070_tune_digital(fe);
        if (ret != FE_CALLBACK_TIME_NEVER)
                msleep(ret/10);
        else
index b174d1c78583ee1001b8892626c80b00450f25fa..224d81e8509136ecaa5334702aaafea81b4135d3 100644 (file)
@@ -717,6 +717,34 @@ static const u16 rf_ramp_pwm_cband_7090[] = {
        (0 << 10) | 109,        /* RF_RAMP4, LNA 4 */
 };
 
+static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
+       186,
+       40,
+       746,
+       (10 << 10) | 345,
+       (0  << 10) | 746,
+       (0 << 10) | 0,
+       (0  << 10) | 0,
+       (28 << 10) | 200,
+       (0  << 10) | 345,
+       (20 << 10) | 0,
+       (0  << 10) | 200,
+};
+
+static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
+       86,
+       40,
+       345,
+       (0 << 10) | 0,
+       (0 << 10) | 0,
+       (0 << 10) | 0,
+       (0 << 10) | 0,
+       (28 << 10) | 200,
+       (0  << 10) | 345,
+       (20 << 10) | 0,
+       (0  << 10) | 200,
+};
+
 static const u16 rf_ramp_pwm_cband_8090[] = {
        345,                    /* max RF gain in 10th of dB */
        29,                     /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
@@ -1076,8 +1104,16 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
                                dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
                                if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
                                        dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
-                               else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
-                                       dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+                               else if (state->identity.version == SOC_7090_P1G_11R1
+                                               || state->identity.version == SOC_7090_P1G_21R1) {
+                                       if (state->config->is_dib7090e) {
+                                               if (state->rf_ramp == NULL)
+                                                       dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
+                                               else
+                                                       dib0090_set_rframp_pwm(state, state->rf_ramp);
+                                       } else
+                                               dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+                               }
                        } else {
                                dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
                                dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
@@ -1112,13 +1148,21 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
                else
                        dib0090_write_reg(state, 0x32, (0 << 11));
 
-               dib0090_write_reg(state, 0x04, 0x01);
+               dib0090_write_reg(state, 0x04, 0x03);
                dib0090_write_reg(state, 0x39, (1 << 10));
        }
 }
 
 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
 
+void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+       if (DC_servo_cutoff < 4)
+               dib0090_write_reg(state, 0x04, DC_servo_cutoff);
+}
+EXPORT_SYMBOL(dib0090_set_dc_servo);
+
 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
 {
        u16 adc_val = dib0090_read_reg(state, 0x1d);
@@ -1305,7 +1349,7 @@ void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 *
 
 EXPORT_SYMBOL(dib0090_get_current_gain);
 
-u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
 {
        struct dib0090_state *state = fe->tuner_priv;
        u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
@@ -1342,9 +1386,57 @@ u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
 
        return state->wbd_offset + wbd_tcold;
 }
+EXPORT_SYMBOL(dib0090_get_wbd_target);
 
+u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+       return state->wbd_offset;
+}
 EXPORT_SYMBOL(dib0090_get_wbd_offset);
 
+int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+
+       dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
+                       | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
+
+       return 0;
+}
+EXPORT_SYMBOL(dib0090_set_switch);
+
+int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+
+       dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
+                       | ((onoff & 1) << 15));
+       return 0;
+}
+EXPORT_SYMBOL(dib0090_set_vga);
+
+int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+
+       if ((!state->identity.p1g) || (!state->identity.in_soc)
+                       || ((state->identity.version != SOC_7090_P1G_21R1)
+                               && (state->identity.version != SOC_7090_P1G_11R1))) {
+               dprintk("%s() function can only be used for dib7090P", __func__);
+               return -ENODEV;
+       }
+
+       if (cfg_sensitivity)
+               state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
+       else
+               state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
+       dib0090_pwm_gain_reset(fe);
+
+       return 0;
+}
+EXPORT_SYMBOL(dib0090_update_rframp_7090);
+
 static const u16 dib0090_defaults[] = {
 
        25, 0x01,
@@ -1430,7 +1522,7 @@ static void dib0090_set_default_config(struct dib0090_state *state, const u16 *
 #define POLY_MIN      (u8)  0
 #define POLY_MAX      (u8)  8
 
-void dib0090_set_EFUSE(struct dib0090_state *state)
+static void dib0090_set_EFUSE(struct dib0090_state *state)
 {
        u8 c, h, n;
        u16 e2, e4;
@@ -1505,7 +1597,10 @@ static int dib0090_reset(struct dvb_frontend *fe)
                dib0090_set_EFUSE(state);
 
        /* Congigure in function of the crystal */
-       if (state->config->io.clock_khz >= 24000)
+       if (state->config->force_crystal_mode != 0)
+               dib0090_write_reg(state, 0x14,
+                               state->config->force_crystal_mode & 3);
+       else if (state->config->io.clock_khz >= 24000)
                dib0090_write_reg(state, 0x14, 1);
        else
                dib0090_write_reg(state, 0x14, 2);
@@ -1951,6 +2046,52 @@ static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
 #endif
 };
 
+static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
+#ifdef CONFIG_BAND_CBAND
+       { 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+       { 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+       { 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+       { 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
+       { 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+       { 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
+#endif
+};
+
+int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+               u8 cfg_sensitivity)
+{
+       struct dib0090_state *state = fe->tuner_priv;
+       const struct dib0090_tuning *tune =
+               dib0090_tuning_table_cband_7090e_sensitivity;
+       const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
+               { 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+               { 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
+               { 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
+       };
+
+       if ((!state->identity.p1g) || (!state->identity.in_soc)
+                       || ((state->identity.version != SOC_7090_P1G_21R1)
+                               && (state->identity.version != SOC_7090_P1G_11R1))) {
+               dprintk("%s() function can only be used for dib7090", __func__);
+               return -ENODEV;
+       }
+
+       if (cfg_sensitivity)
+               tune = dib0090_tuning_table_cband_7090e_sensitivity;
+       else
+               tune = dib0090_tuning_table_cband_7090e_aci;
+
+       while (state->rf_request > tune->max_freq)
+               tune++;
+
+       dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
+                       | (tune->lna_bias & 0x7fff));
+       dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
+                       | ((tune->lna_tune << 6) & 0x07c0));
+       return 0;
+}
+EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
+
 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
 {
        int ret = 0;
@@ -2199,12 +2340,18 @@ static int dib0090_tune(struct dvb_frontend *fe)
                                        if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
                                                        || state->current_band & BAND_UHF) {
                                                state->current_band = BAND_CBAND;
-                                               tune = dib0090_tuning_table_cband_7090;
+                                               if (state->config->is_dib7090e)
+                                                       tune = dib0090_tuning_table_cband_7090e_sensitivity;
+                                               else
+                                                       tune = dib0090_tuning_table_cband_7090;
                                        }
                                } else {        /* Use the CBAND input for all band under UHF */
                                        if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
                                                state->current_band = BAND_CBAND;
-                                               tune = dib0090_tuning_table_cband_7090;
+                                               if (state->config->is_dib7090e)
+                                                       tune = dib0090_tuning_table_cband_7090e_sensitivity;
+                                               else
+                                                       tune = dib0090_tuning_table_cband_7090;
                                        }
                                }
                        } else
@@ -2419,7 +2566,7 @@ static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
        return 0;
 }
 
-static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dib0090_set_params(struct dvb_frontend *fe)
 {
        struct dib0090_state *state = fe->tuner_priv;
        u32 ret;
index 13d85244ec160048cec20fb9ee6ac16f0a3211ca..781dc49de45b218b779411b413a565012761995b 100644 (file)
@@ -71,6 +71,8 @@ struct dib0090_config {
        u8 fref_clock_ratio;
        u16 force_cband_input;
        struct dib0090_wbd_slope *wbd;
+       u8 is_dib7090e;
+       u8 force_crystal_mode;
 };
 
 #if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
@@ -78,13 +80,21 @@ extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c
 extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
 extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
-extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
+extern u16 dib0090_get_wbd_target(struct dvb_frontend *tuner);
+extern u16 dib0090_get_wbd_offset(struct dvb_frontend *fe);
 extern int dib0090_gain_control(struct dvb_frontend *fe);
 extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
 extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
 extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
+extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff);
+extern int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3);
+extern int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff);
+extern int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+               u8 cfg_sensitivity);
+extern int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+               u8 cfg_sensitivity);
 #else
-static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
+static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
@@ -106,7 +116,13 @@ static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 }
 
-static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
+static inline u16 dib0090_get_wbd_target(struct dvb_frontend *tuner)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return 0;
@@ -134,6 +150,38 @@ static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 }
+
+static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int dib0090_set_switch(struct dvb_frontend *fe,
+               u8 sw1, u8 sw2, u8 sw3)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+
+static inline int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+
+static inline int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+               u8 cfg_sensitivity)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+
+static inline int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+               u8 cfg_sensitivity)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
 #endif
 
 #endif
index 437904cbf3e6c5000660da6da0c92aeda5e4da99..af91e0c92339a994dea3a342c869aa9d43441489 100644 (file)
@@ -112,39 +112,37 @@ static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
                }
        };
 
-static int dib3000mb_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep);
+static int dib3000mb_get_frontend(struct dvb_frontend* fe);
 
-static int dib3000mb_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep, int tuner)
+static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
 {
        struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        fe_code_rate_t fe_cr = FEC_NONE;
        int search_state, seq;
 
        if (tuner && fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, fep);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
                deb_setf("bandwidth: ");
-               switch (ofdm->bandwidth) {
-                       case BANDWIDTH_8_MHZ:
+               switch (c->bandwidth_hz) {
+                       case 8000000:
                                deb_setf("8 MHz\n");
                                wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
                                wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
                                break;
-                       case BANDWIDTH_7_MHZ:
+                       case 7000000:
                                deb_setf("7 MHz\n");
                                wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
                                wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
                                break;
-                       case BANDWIDTH_6_MHZ:
+                       case 6000000:
                                deb_setf("6 MHz\n");
                                wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
                                wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
                                break;
-                       case BANDWIDTH_AUTO:
+                       case 0:
                                return -EOPNOTSUPP;
                        default:
                                err("unknown bandwidth value.");
@@ -154,7 +152,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
 
        deb_setf("transmission mode: ");
-       switch (ofdm->transmission_mode) {
+       switch (c->transmission_mode) {
                case TRANSMISSION_MODE_2K:
                        deb_setf("2k\n");
                        wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
@@ -171,7 +169,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        }
 
        deb_setf("guard: ");
-       switch (ofdm->guard_interval) {
+       switch (c->guard_interval) {
                case GUARD_INTERVAL_1_32:
                        deb_setf("1_32\n");
                        wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
@@ -196,7 +194,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        }
 
        deb_setf("inversion: ");
-       switch (fep->inversion) {
+       switch (c->inversion) {
                case INVERSION_OFF:
                        deb_setf("off\n");
                        wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
@@ -212,8 +210,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
                        return -EINVAL;
        }
 
-       deb_setf("constellation: ");
-       switch (ofdm->constellation) {
+       deb_setf("modulation: ");
+       switch (c->modulation) {
                case QPSK:
                        deb_setf("qpsk\n");
                        wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
@@ -232,7 +230,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
                        return -EINVAL;
        }
        deb_setf("hierarchy: ");
-       switch (ofdm->hierarchy_information) {
+       switch (c->hierarchy) {
                case HIERARCHY_NONE:
                        deb_setf("none ");
                        /* fall through */
@@ -256,16 +254,16 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        }
 
        deb_setf("hierarchy: ");
-       if (ofdm->hierarchy_information == HIERARCHY_NONE) {
+       if (c->hierarchy == HIERARCHY_NONE) {
                deb_setf("none\n");
                wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
                wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
-               fe_cr = ofdm->code_rate_HP;
-       } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
+               fe_cr = c->code_rate_HP;
+       } else if (c->hierarchy != HIERARCHY_AUTO) {
                deb_setf("on\n");
                wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
                wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
-               fe_cr = ofdm->code_rate_LP;
+               fe_cr = c->code_rate_LP;
        }
        deb_setf("fec: ");
        switch (fe_cr) {
@@ -300,9 +298,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        }
 
        seq = dib3000_seq
-               [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]
-               [ofdm->guard_interval == GUARD_INTERVAL_AUTO]
-               [fep->inversion == INVERSION_AUTO];
+               [c->transmission_mode == TRANSMISSION_MODE_AUTO]
+               [c->guard_interval == GUARD_INTERVAL_AUTO]
+               [c->inversion == INVERSION_AUTO];
 
        deb_setf("seq? %d\n", seq);
 
@@ -310,8 +308,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
 
        wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
 
-       if (ofdm->transmission_mode == TRANSMISSION_MODE_2K) {
-               if (ofdm->guard_interval == GUARD_INTERVAL_1_8) {
+       if (c->transmission_mode == TRANSMISSION_MODE_2K) {
+               if (c->guard_interval == GUARD_INTERVAL_1_8) {
                        wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
                } else {
                        wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
@@ -339,10 +337,10 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
 
        /* something has to be auto searched */
-       if (ofdm->constellation == QAM_AUTO ||
-               ofdm->hierarchy_information == HIERARCHY_AUTO ||
+       if (c->modulation == QAM_AUTO ||
+               c->hierarchy == HIERARCHY_AUTO ||
                fe_cr == FEC_AUTO ||
-               fep->inversion == INVERSION_AUTO) {
+               c->inversion == INVERSION_AUTO) {
                int as_count=0;
 
                deb_setf("autosearch enabled.\n");
@@ -361,10 +359,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
                deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
 
                if (search_state == 1) {
-                       struct dvb_frontend_parameters feps;
-                       if (dib3000mb_get_frontend(fe, &feps) == 0) {
+                       if (dib3000mb_get_frontend(fe) == 0) {
                                deb_setf("reading tuning data from frontend succeeded.\n");
-                               return dib3000mb_set_frontend(fe, &feps, 0);
+                               return dib3000mb_set_frontend(fe, 0);
                        }
                }
 
@@ -453,11 +450,10 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
        return 0;
 }
 
-static int dib3000mb_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int dib3000mb_get_frontend(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
        fe_code_rate_t *cr;
        u16 tps_val;
        int inv_test1,inv_test2;
@@ -484,25 +480,25 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
        else
                inv_test2 = 2;
 
-       fep->inversion =
+       c->inversion =
                ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
                ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
                INVERSION_ON : INVERSION_OFF;
 
-       deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+       deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);
 
        switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
                case DIB3000_CONSTELLATION_QPSK:
                        deb_getf("QPSK ");
-                       ofdm->constellation = QPSK;
+                       c->modulation = QPSK;
                        break;
                case DIB3000_CONSTELLATION_16QAM:
                        deb_getf("QAM16 ");
-                       ofdm->constellation = QAM_16;
+                       c->modulation = QAM_16;
                        break;
                case DIB3000_CONSTELLATION_64QAM:
                        deb_getf("QAM64 ");
-                       ofdm->constellation = QAM_64;
+                       c->modulation = QAM_64;
                        break;
                default:
                        err("Unexpected constellation returned by TPS (%d)", tps_val);
@@ -512,24 +508,24 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
 
        if (rd(DIB3000MB_REG_TPS_HRCH)) {
                deb_getf("HRCH ON\n");
-               cr = &ofdm->code_rate_LP;
-               ofdm->code_rate_HP = FEC_NONE;
+               cr = &c->code_rate_LP;
+               c->code_rate_HP = FEC_NONE;
                switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
                        case DIB3000_ALPHA_0:
                                deb_getf("HIERARCHY_NONE ");
-                               ofdm->hierarchy_information = HIERARCHY_NONE;
+                               c->hierarchy = HIERARCHY_NONE;
                                break;
                        case DIB3000_ALPHA_1:
                                deb_getf("HIERARCHY_1 ");
-                               ofdm->hierarchy_information = HIERARCHY_1;
+                               c->hierarchy = HIERARCHY_1;
                                break;
                        case DIB3000_ALPHA_2:
                                deb_getf("HIERARCHY_2 ");
-                               ofdm->hierarchy_information = HIERARCHY_2;
+                               c->hierarchy = HIERARCHY_2;
                                break;
                        case DIB3000_ALPHA_4:
                                deb_getf("HIERARCHY_4 ");
-                               ofdm->hierarchy_information = HIERARCHY_4;
+                               c->hierarchy = HIERARCHY_4;
                                break;
                        default:
                                err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
@@ -540,9 +536,9 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
                tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
        } else {
                deb_getf("HRCH OFF\n");
-               cr = &ofdm->code_rate_HP;
-               ofdm->code_rate_LP = FEC_NONE;
-               ofdm->hierarchy_information = HIERARCHY_NONE;
+               cr = &c->code_rate_HP;
+               c->code_rate_LP = FEC_NONE;
+               c->hierarchy = HIERARCHY_NONE;
 
                tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
        }
@@ -577,19 +573,19 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
        switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
                case DIB3000_GUARD_TIME_1_32:
                        deb_getf("GUARD_INTERVAL_1_32 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_32;
+                       c->guard_interval = GUARD_INTERVAL_1_32;
                        break;
                case DIB3000_GUARD_TIME_1_16:
                        deb_getf("GUARD_INTERVAL_1_16 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_16;
+                       c->guard_interval = GUARD_INTERVAL_1_16;
                        break;
                case DIB3000_GUARD_TIME_1_8:
                        deb_getf("GUARD_INTERVAL_1_8 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_8;
+                       c->guard_interval = GUARD_INTERVAL_1_8;
                        break;
                case DIB3000_GUARD_TIME_1_4:
                        deb_getf("GUARD_INTERVAL_1_4 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_4;
+                       c->guard_interval = GUARD_INTERVAL_1_4;
                        break;
                default:
                        err("Unexpected Guard Time returned by TPS (%d)", tps_val);
@@ -600,11 +596,11 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
        switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
                case DIB3000_TRANSMISSION_MODE_2K:
                        deb_getf("TRANSMISSION_MODE_2K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_2K;
+                       c->transmission_mode = TRANSMISSION_MODE_2K;
                        break;
                case DIB3000_TRANSMISSION_MODE_8K:
                        deb_getf("TRANSMISSION_MODE_8K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_8K;
+                       c->transmission_mode = TRANSMISSION_MODE_8K;
                        break;
                default:
                        err("unexpected transmission mode return by TPS (%d)", tps_val);
@@ -701,9 +697,9 @@ static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)
        return dib3000mb_fe_init(fe, 0);
 }
 
-static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
+static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)
 {
-       return dib3000mb_set_frontend(fe, fep, 1);
+       return dib3000mb_set_frontend(fe, 1);
 }
 
 static void dib3000mb_release(struct dvb_frontend* fe)
@@ -794,10 +790,9 @@ error:
 }
 
 static struct dvb_frontend_ops dib3000mb_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "DiBcom 3000M-B DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 44250000,
                .frequency_max          = 867250000,
                .frequency_stepsize     = 62500,
index 16c526591f363c512e96d464b75548ee599a3dc3..9dc235aa44b71a712ba7c57918f9c786dd237e15 100644 (file)
@@ -98,7 +98,7 @@ struct dib3000_state {
        int timing_offset;
        int timing_offset_comp_done;
 
-       fe_bandwidth_t last_tuned_bw;
+       u32 last_tuned_bw;
        u32 last_tuned_freq;
 };
 
index 088e7fadbe3db11d01828606ed478096086c5c51..ffad181a96920bf90250d3aba9757247f1b56cec 100644 (file)
@@ -40,7 +40,7 @@ struct dib3000mc_state {
 
        u32 timf;
 
-       fe_bandwidth_t current_bandwidth;
+       u32 current_bandwidth;
 
        u16 dev_id;
 
@@ -438,11 +438,14 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
                dib3000mc_write_word(state, reg, cfg[reg - 129]);
 }
 
-static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_frontend_parameters *ch, u16 seq)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
+                                     struct dtv_frontend_properties *ch, u16 seq)
 {
        u16 value;
-    dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
-       dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 0);
+       u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+
+       dib3000mc_set_bandwidth(state, bw);
+       dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
 
 //     if (boost)
 //             dib3000mc_write_word(state, 100, (11 << 6) + 6);
@@ -471,22 +474,22 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
        dib3000mc_write_word(state, 97,0);
        dib3000mc_write_word(state, 98,0);
 
-       dib3000mc_set_impulse_noise(state, 0, ch->u.ofdm.transmission_mode);
+       dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
 
        value = 0;
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
                default:
                case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
                case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
                case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
                case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
                default:
                case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
        }
-       switch (ch->u.ofdm.constellation) {
+       switch (ch->modulation) {
                case QPSK:  value |= (0 << 3); break;
                case QAM_16: value |= (1 << 3); break;
                default:
@@ -502,11 +505,11 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
        dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
 
        value = 0;
-       if (ch->u.ofdm.hierarchy_information == 1)
+       if (ch->hierarchy == 1)
                value |= (1 << 4);
        if (1 == 1)
                value |= 1;
-       switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+       switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
                case FEC_2_3: value |= (2 << 1); break;
                case FEC_3_4: value |= (3 << 1); break;
                case FEC_5_6: value |= (5 << 1); break;
@@ -517,12 +520,12 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
        dib3000mc_write_word(state, 181, value);
 
        // diversity synchro delay add 50% SFN margin
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_8K: value = 256; break;
                case TRANSMISSION_MODE_2K:
                default: value = 64; break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
                case GUARD_INTERVAL_1_16: value *= 2; break;
                case GUARD_INTERVAL_1_8:  value *= 4; break;
                case GUARD_INTERVAL_1_4:  value *= 8; break;
@@ -540,27 +543,28 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
 
        msleep(30);
 
-       dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->u.ofdm.transmission_mode);
+       dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
 }
 
-static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *chan)
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
        struct dib3000mc_state *state = demod->demodulator_priv;
        u16 reg;
 //     u32 val;
-       struct dvb_frontend_parameters schan;
+       struct dtv_frontend_properties schan;
 
        schan = *chan;
 
        /* TODO what is that ? */
 
        /* a channel for autosearch */
-       schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
-       schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
-       schan.u.ofdm.constellation = QAM_64;
-       schan.u.ofdm.code_rate_HP = FEC_2_3;
-       schan.u.ofdm.code_rate_LP = FEC_2_3;
-       schan.u.ofdm.hierarchy_information = 0;
+       schan.transmission_mode = TRANSMISSION_MODE_8K;
+       schan.guard_interval = GUARD_INTERVAL_1_32;
+       schan.modulation = QAM_64;
+       schan.code_rate_HP = FEC_2_3;
+       schan.code_rate_LP = FEC_2_3;
+       schan.hierarchy = 0;
 
        dib3000mc_set_channel_cfg(state, &schan, 11);
 
@@ -586,8 +590,9 @@ static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
        return 0; // still pending
 }
 
-static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib3000mc_tune(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib3000mc_state *state = demod->demodulator_priv;
 
        // ** configure demod **
@@ -603,8 +608,8 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parame
                dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
        }
 
-       dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation);
-       if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) {
+       dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
+       if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
                dib3000mc_write_word(state, 26, 38528);
                dib3000mc_write_word(state, 33, 8);
        } else {
@@ -613,7 +618,8 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parame
        }
 
        if (dib3000mc_read_word(state, 509) & 0x80)
-               dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 1);
+               dib3000mc_set_timing(state, ch->transmission_mode,
+                                    BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
 
        return 0;
 }
@@ -626,87 +632,87 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
 
 EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
 
-static int dib3000mc_get_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *fep)
+static int dib3000mc_get_frontend(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib3000mc_state *state = fe->demodulator_priv;
        u16 tps = dib3000mc_read_word(state,458);
 
        fep->inversion = INVERSION_AUTO;
 
-       fep->u.ofdm.bandwidth = state->current_bandwidth;
+       fep->bandwidth_hz = state->current_bandwidth;
 
        switch ((tps >> 8) & 0x1) {
-               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
-               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+               case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
        }
 
        switch (tps & 0x3) {
-               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
-               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
-               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
-               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+               case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
        }
 
        switch ((tps >> 13) & 0x3) {
-               case 0: fep->u.ofdm.constellation = QPSK; break;
-               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 0: fep->modulation = QPSK; break;
+               case 1: fep->modulation = QAM_16; break;
                case 2:
-               default: fep->u.ofdm.constellation = QAM_64; break;
+               default: fep->modulation = QAM_64; break;
        }
 
        /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
        /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
 
-       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       fep->hierarchy = HIERARCHY_NONE;
        switch ((tps >> 5) & 0x7) {
-               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
-               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
-               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
-               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 1: fep->code_rate_HP = FEC_1_2; break;
+               case 2: fep->code_rate_HP = FEC_2_3; break;
+               case 3: fep->code_rate_HP = FEC_3_4; break;
+               case 5: fep->code_rate_HP = FEC_5_6; break;
                case 7:
-               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+               default: fep->code_rate_HP = FEC_7_8; break;
 
        }
 
        switch ((tps >> 2) & 0x7) {
-               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
-               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
-               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
-               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 1: fep->code_rate_LP = FEC_1_2; break;
+               case 2: fep->code_rate_LP = FEC_2_3; break;
+               case 3: fep->code_rate_LP = FEC_3_4; break;
+               case 5: fep->code_rate_LP = FEC_5_6; break;
                case 7:
-               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+               default: fep->code_rate_LP = FEC_7_8; break;
        }
 
        return 0;
 }
 
-static int dib3000mc_set_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *fep)
+static int dib3000mc_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib3000mc_state *state = fe->demodulator_priv;
-    int ret;
+       int ret;
 
        dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
 
-       state->current_bandwidth = fep->u.ofdm.bandwidth;
-       dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+       state->current_bandwidth = fep->bandwidth_hz;
+       dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
 
        /* maybe the parameter has been changed */
        state->sfn_workaround_active = buggy_sfn_workaround;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, fep);
+               fe->ops.tuner_ops.set_params(fe);
                msleep(100);
        }
 
-       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
-               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
-               fep->u.ofdm.constellation     == QAM_AUTO ||
-               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+       if (fep->transmission_mode  == TRANSMISSION_MODE_AUTO ||
+           fep->guard_interval == GUARD_INTERVAL_AUTO ||
+           fep->modulation     == QAM_AUTO ||
+           fep->code_rate_HP   == FEC_AUTO) {
                int i = 1000, found;
 
-               dib3000mc_autosearch_start(fe, fep);
+               dib3000mc_autosearch_start(fe);
                do {
                        msleep(1);
                        found = dib3000mc_autosearch_is_irq(fe);
@@ -716,14 +722,14 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
                if (found == 0 || found == 1)
                        return 0; // no channel found
 
-               dib3000mc_get_frontend(fe, fep);
+               dib3000mc_get_frontend(fe);
        }
 
-    ret = dib3000mc_tune(fe, fep);
+       ret = dib3000mc_tune(fe);
 
        /* make this a config parameter */
        dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
-    return ret;
+       return ret;
 }
 
 static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -897,9 +903,9 @@ error:
 EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "DiBcom 3000MC/P",
-               .type = FE_OFDM,
                .frequency_min      = 44250000,
                .frequency_max      = 867250000,
                .frequency_stepsize = 62500,
index dbb76d75c932fecb36784a62be7451a3d63fb4c8..148bf79236fbcb858e01d98500424939b03a6f47 100644 (file)
@@ -38,7 +38,7 @@ struct dib7000m_state {
        u16 wbd_ref;
 
        u8 current_band;
-       fe_bandwidth_t current_bandwidth;
+       u32 current_bandwidth;
        struct dibx000_agc_config *current_agc;
        u32 timf;
        u32 timf_default;
@@ -313,6 +313,9 @@ static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
 {
        u32 timf;
 
+       if (!bw)
+               bw = 8000;
+
        // store the current bandwidth for later use
        state->current_bandwidth = bw;
 
@@ -742,8 +745,9 @@ static void dib7000m_update_timf(struct dib7000m_state *state)
        dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
 }
 
-static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_agc_startup(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000m_state *state = demod->demodulator_priv;
        u16 cfg_72 = dib7000m_read_word(state, 72);
        int ret = -1;
@@ -832,28 +836,29 @@ static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_
        return ret;
 }
 
-static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch,
+                                u8 seq)
 {
        u16 value, est[4];
 
-       dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+       dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
 
        /* nfft, guard, qam, alpha */
        value = 0;
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
                case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
                default:
                case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
                case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
                case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
                case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
                default:
                case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
        }
-       switch (ch->u.ofdm.constellation) {
+       switch (ch->modulation) {
                case QPSK:  value |= (0 << 3); break;
                case QAM_16: value |= (1 << 3); break;
                default:
@@ -872,11 +877,11 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
        value = 0;
        if (1 != 0)
                value |= (1 << 6);
-       if (ch->u.ofdm.hierarchy_information == 1)
+       if (ch->hierarchy == 1)
                value |= (1 << 4);
        if (1 == 1)
                value |= 1;
-       switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+       switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
                case FEC_2_3: value |= (2 << 1); break;
                case FEC_3_4: value |= (3 << 1); break;
                case FEC_5_6: value |= (5 << 1); break;
@@ -901,13 +906,13 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
        dib7000m_write_word(state, 33, (0 << 4) | 0x5);
 
        /* P_dvsy_sync_wait */
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_8K: value = 256; break;
                case TRANSMISSION_MODE_4K: value = 128; break;
                case TRANSMISSION_MODE_2K:
                default: value = 64; break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
                case GUARD_INTERVAL_1_16: value *= 2; break;
                case GUARD_INTERVAL_1_8:  value *= 4; break;
                case GUARD_INTERVAL_1_4:  value *= 8; break;
@@ -925,7 +930,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
        dib7000m_set_diversity_in(&state->demod, state->div_state);
 
        /* channel estimation fine configuration */
-       switch (ch->u.ofdm.constellation) {
+       switch (ch->modulation) {
                case QAM_64:
                        est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
                        est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
@@ -952,25 +957,26 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
        dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
 }
 
-static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_autosearch_start(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000m_state *state = demod->demodulator_priv;
-       struct dvb_frontend_parameters schan;
+       struct dtv_frontend_properties schan;
        int ret = 0;
        u32 value, factor;
 
        schan = *ch;
 
-       schan.u.ofdm.constellation = QAM_64;
-       schan.u.ofdm.guard_interval        = GUARD_INTERVAL_1_32;
-       schan.u.ofdm.transmission_mode         = TRANSMISSION_MODE_8K;
-       schan.u.ofdm.code_rate_HP = FEC_2_3;
-       schan.u.ofdm.code_rate_LP = FEC_3_4;
-       schan.u.ofdm.hierarchy_information         = 0;
+       schan.modulation = QAM_64;
+       schan.guard_interval        = GUARD_INTERVAL_1_32;
+       schan.transmission_mode         = TRANSMISSION_MODE_8K;
+       schan.code_rate_HP = FEC_2_3;
+       schan.code_rate_LP = FEC_3_4;
+       schan.hierarchy    = 0;
 
        dib7000m_set_channel(state, &schan, 7);
 
-       factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
+       factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz);
        if (factor >= 5000)
                factor = 1;
        else
@@ -1027,8 +1033,9 @@ static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
                return dib7000m_autosearch_irq(state, 537);
 }
 
-static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_tune(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000m_state *state = demod->demodulator_priv;
        int ret = 0;
        u16 value;
@@ -1055,7 +1062,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
        //dump_reg(state);
        /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
        value = (6 << 8) | 0x80;
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
                case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
                default:
@@ -1065,7 +1072,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
 
        /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
        value = (0 << 4);
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_2K: value |= 0x6; break;
                case TRANSMISSION_MODE_4K: value |= 0x7; break;
                default:
@@ -1075,7 +1082,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
 
        /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
        value = (0 << 4);
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
                case TRANSMISSION_MODE_2K: value |= 0x6; break;
                case TRANSMISSION_MODE_4K: value |= 0x7; break;
                default:
@@ -1087,7 +1094,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
        if ((dib7000m_read_word(state, 535) >> 6)  & 0x1)
                dib7000m_update_timf(state);
 
-    dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+       dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
        return ret;
 }
 
@@ -1147,57 +1154,57 @@ static int dib7000m_identify(struct dib7000m_state *state)
 }
 
 
-static int dib7000m_get_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *fep)
+static int dib7000m_get_frontend(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib7000m_state *state = fe->demodulator_priv;
        u16 tps = dib7000m_read_word(state,480);
 
        fep->inversion = INVERSION_AUTO;
 
-       fep->u.ofdm.bandwidth = state->current_bandwidth;
+       fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
 
        switch ((tps >> 8) & 0x3) {
-               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
-               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
-               /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+               case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
+               /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
        }
 
        switch (tps & 0x3) {
-               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
-               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
-               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
-               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+               case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
        }
 
        switch ((tps >> 14) & 0x3) {
-               case 0: fep->u.ofdm.constellation = QPSK; break;
-               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 0: fep->modulation = QPSK; break;
+               case 1: fep->modulation = QAM_16; break;
                case 2:
-               default: fep->u.ofdm.constellation = QAM_64; break;
+               default: fep->modulation = QAM_64; break;
        }
 
        /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
        /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
 
-       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       fep->hierarchy = HIERARCHY_NONE;
        switch ((tps >> 5) & 0x7) {
-               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
-               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
-               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
-               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 1: fep->code_rate_HP = FEC_1_2; break;
+               case 2: fep->code_rate_HP = FEC_2_3; break;
+               case 3: fep->code_rate_HP = FEC_3_4; break;
+               case 5: fep->code_rate_HP = FEC_5_6; break;
                case 7:
-               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+               default: fep->code_rate_HP = FEC_7_8; break;
 
        }
 
        switch ((tps >> 2) & 0x7) {
-               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
-               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
-               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
-               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 1: fep->code_rate_LP = FEC_1_2; break;
+               case 2: fep->code_rate_LP = FEC_2_3; break;
+               case 3: fep->code_rate_LP = FEC_3_4; break;
+               case 5: fep->code_rate_LP = FEC_5_6; break;
                case 7:
-               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+               default: fep->code_rate_LP = FEC_7_8; break;
        }
 
        /* native interleaver: (dib7000m_read_word(state, 481) >>  5) & 0x1 */
@@ -1205,35 +1212,34 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
-static int dib7000m_set_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *fep)
+static int dib7000m_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib7000m_state *state = fe->demodulator_priv;
        int time, ret;
 
-    dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
+       dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
 
-       state->current_bandwidth = fep->u.ofdm.bandwidth;
-       dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+       dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
 
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, fep);
+               fe->ops.tuner_ops.set_params(fe);
 
        /* start up the AGC */
        state->agc_state = 0;
        do {
-               time = dib7000m_agc_startup(fe, fep);
+               time = dib7000m_agc_startup(fe);
                if (time != -1)
                        msleep(time);
        } while (time != -1);
 
-       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
-               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
-               fep->u.ofdm.constellation     == QAM_AUTO ||
-               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+       if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->guard_interval    == GUARD_INTERVAL_AUTO ||
+               fep->modulation        == QAM_AUTO ||
+               fep->code_rate_HP      == FEC_AUTO) {
                int i = 800, found;
 
-               dib7000m_autosearch_start(fe, fep);
+               dib7000m_autosearch_start(fe);
                do {
                        msleep(1);
                        found = dib7000m_autosearch_is_irq(fe);
@@ -1243,10 +1249,10 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
                if (found == 0 || found == 1)
                        return 0; // no channel found
 
-               dib7000m_get_frontend(fe, fep);
+               dib7000m_get_frontend(fe);
        }
 
-       ret = dib7000m_tune(fe, fep);
+       ret = dib7000m_tune(fe);
 
        /* make this a config parameter */
        dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
@@ -1430,9 +1436,9 @@ error:
 EXPORT_SYMBOL(dib7000m_attach);
 
 static struct dvb_frontend_ops dib7000m_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "DiBcom 7000MA/MB/PA/PB/MC",
-               .type = FE_OFDM,
                .frequency_min      = 44250000,
                .frequency_max      = 867250000,
                .frequency_stepsize = 62500,
index ce8534ff142efe448de4cf2b7f325edc74fadaab..5ceadc285b3ad59ef187d4c074db352ff1155d5c 100644 (file)
@@ -70,6 +70,8 @@ struct dib7000p_state {
        u8 i2c_write_buffer[4];
        u8 i2c_read_buffer[2];
        struct mutex i2c_buffer_lock;
+
+       u8 input_mode_mpeg;
 };
 
 enum dib7000p_power_mode {
@@ -78,8 +80,11 @@ enum dib7000p_power_mode {
        DIB7000P_POWER_INTERFACE_ONLY,
 };
 
+/* dib7090 specific fonctions */
 static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
 static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
 
 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
 {
@@ -276,17 +281,23 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p
        dib7000p_write_word(state, 774, reg_774);
        dib7000p_write_word(state, 775, reg_775);
        dib7000p_write_word(state, 776, reg_776);
-       dib7000p_write_word(state, 899, reg_899);
        dib7000p_write_word(state, 1280, reg_1280);
+       if (state->version != SOC7090)
+               dib7000p_write_word(state, 899, reg_899);
 
        return 0;
 }
 
 static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
 {
-       u16 reg_908 = dib7000p_read_word(state, 908), reg_909 = dib7000p_read_word(state, 909);
+       u16 reg_908 = 0, reg_909 = 0;
        u16 reg;
 
+       if (state->version != SOC7090) {
+               reg_908 = dib7000p_read_word(state, 908);
+               reg_909 = dib7000p_read_word(state, 909);
+       }
+
        switch (no) {
        case DIBX000_SLOW_ADC_ON:
                if (state->version == SOC7090) {
@@ -342,8 +353,10 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad
        reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
        reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
 
-       dib7000p_write_word(state, 908, reg_908);
-       dib7000p_write_word(state, 909, reg_909);
+       if (state->version != SOC7090) {
+               dib7000p_write_word(state, 908, reg_908);
+               dib7000p_write_word(state, 909, reg_909);
+       }
 }
 
 static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
@@ -398,6 +411,24 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
 }
 EXPORT_SYMBOL(dib7000p_set_wbd_ref);
 
+int dib7000p_get_agc_values(struct dvb_frontend *fe,
+               u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+       struct dib7000p_state *state = fe->demodulator_priv;
+
+       if (agc_global != NULL)
+               *agc_global = dib7000p_read_word(state, 394);
+       if (agc1 != NULL)
+               *agc1 = dib7000p_read_word(state, 392);
+       if (agc2 != NULL)
+               *agc2 = dib7000p_read_word(state, 393);
+       if (wbd != NULL)
+               *wbd = dib7000p_read_word(state, 397);
+
+       return 0;
+}
+EXPORT_SYMBOL(dib7000p_get_agc_values);
+
 static void dib7000p_reset_pll(struct dib7000p_state *state)
 {
        struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
@@ -519,7 +550,7 @@ static u16 dib7000p_defaults[] = {
        // auto search configuration
        3, 2,
        0x0004,
-       0x1000,
+       (1<<3)|(1<<11)|(1<<12)|(1<<13),
        0x0814,                 /* Equal Lock */
 
        12, 6,
@@ -595,13 +626,6 @@ static u16 dib7000p_defaults[] = {
        1, 235,
        0x0062,
 
-       2, 901,
-       0x0006,
-       (3 << 10) | (1 << 6),
-
-       1, 905,
-       0x2c8e,
-
        0,
 };
 
@@ -618,15 +642,18 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
        dib7000p_write_word(state, 770, 0xffff);
        dib7000p_write_word(state, 771, 0xffff);
        dib7000p_write_word(state, 772, 0x001f);
-       dib7000p_write_word(state, 898, 0x0003);
        dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
 
        dib7000p_write_word(state, 770, 0);
        dib7000p_write_word(state, 771, 0);
        dib7000p_write_word(state, 772, 0);
-       dib7000p_write_word(state, 898, 0);
        dib7000p_write_word(state, 1280, 0);
 
+       if (state->version != SOC7090) {
+               dib7000p_write_word(state,  898, 0x0003);
+               dib7000p_write_word(state,  898, 0);
+       }
+
        /* default */
        dib7000p_reset_pll(state);
 
@@ -640,7 +667,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
                dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
                dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
                dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
-               dib7000p_write_word(state, 273, (1<<6) | 30);
+               dib7000p_write_word(state, 273, (0<<6) | 30);
        }
        if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
                dprintk("OUTPUT_MODE could not be reset.");
@@ -655,7 +682,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
        dib7000p_set_bandwidth(state, 8000);
 
        if (state->version == SOC7090) {
-               dib7000p_write_word(state, 36, 0x5755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
+               dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
        } else {
                if (state->cfg.tuner_is_baseband)
                        dib7000p_write_word(state, 36, 0x0755);
@@ -664,6 +691,11 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
        }
 
        dib7000p_write_tab(state, dib7000p_defaults);
+       if (state->version != SOC7090) {
+               dib7000p_write_word(state, 901, 0x0006);
+               dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
+               dib7000p_write_word(state, 905, 0x2c8e);
+       }
 
        dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
 
@@ -780,8 +812,9 @@ static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
        }
 }
 
-static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_agc_startup(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000p_state *state = demod->demodulator_priv;
        int ret = -1;
        u8 *agc_state = &state->agc_state;
@@ -904,15 +937,16 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
 }
 EXPORT_SYMBOL(dib7000p_ctrl_timf);
 
-static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
+static void dib7000p_set_channel(struct dib7000p_state *state,
+                                struct dtv_frontend_properties *ch, u8 seq)
 {
        u16 value, est[4];
 
-       dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+       dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
 
        /* nfft, guard, qam, alpha */
        value = 0;
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                value |= (0 << 7);
                break;
@@ -924,7 +958,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                value |= (1 << 7);
                break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
        case GUARD_INTERVAL_1_32:
                value |= (0 << 5);
                break;
@@ -939,7 +973,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                value |= (2 << 5);
                break;
        }
-       switch (ch->u.ofdm.constellation) {
+       switch (ch->modulation) {
        case QPSK:
                value |= (0 << 3);
                break;
@@ -970,11 +1004,11 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
        value = 0;
        if (1 != 0)
                value |= (1 << 6);
-       if (ch->u.ofdm.hierarchy_information == 1)
+       if (ch->hierarchy == 1)
                value |= (1 << 4);
        if (1 == 1)
                value |= 1;
-       switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+       switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
        case FEC_2_3:
                value |= (2 << 1);
                break;
@@ -1001,7 +1035,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
        dib7000p_write_word(state, 33, 0x0005);
 
        /* P_dvsy_sync_wait */
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
        case TRANSMISSION_MODE_8K:
                value = 256;
                break;
@@ -1013,7 +1047,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                value = 64;
                break;
        }
-       switch (ch->u.ofdm.guard_interval) {
+       switch (ch->guard_interval) {
        case GUARD_INTERVAL_1_16:
                value *= 2;
                break;
@@ -1034,11 +1068,11 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
 
        /* deactive the possibility of diversity reception if extended interleaver */
-       state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
+       state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
        dib7000p_set_diversity_in(&state->demod, state->div_state);
 
        /* channel estimation fine configuration */
-       switch (ch->u.ofdm.constellation) {
+       switch (ch->modulation) {
        case QAM_64:
                est[0] = 0x0148;        /* P_adp_regul_cnt 0.04 */
                est[1] = 0xfff0;        /* P_adp_noise_cnt -0.002 */
@@ -1062,27 +1096,31 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
                dib7000p_write_word(state, 187 + value, est[value]);
 }
 
-static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_autosearch_start(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000p_state *state = demod->demodulator_priv;
-       struct dvb_frontend_parameters schan;
+       struct dtv_frontend_properties schan;
        u32 value, factor;
        u32 internal = dib7000p_get_internal_freq(state);
 
        schan = *ch;
-       schan.u.ofdm.constellation = QAM_64;
-       schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
-       schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
-       schan.u.ofdm.code_rate_HP = FEC_2_3;
-       schan.u.ofdm.code_rate_LP = FEC_3_4;
-       schan.u.ofdm.hierarchy_information = 0;
+       schan.modulation = QAM_64;
+       schan.guard_interval = GUARD_INTERVAL_1_32;
+       schan.transmission_mode = TRANSMISSION_MODE_8K;
+       schan.code_rate_HP = FEC_2_3;
+       schan.code_rate_LP = FEC_3_4;
+       schan.hierarchy = 0;
 
        dib7000p_set_channel(state, &schan, 7);
 
-       factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
-       if (factor >= 5000)
-               factor = 1;
-       else
+       factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+       if (factor >= 5000) {
+               if (state->version == SOC7090)
+                       factor = 2;
+               else
+                       factor = 1;
+       } else
                factor = 6;
 
        value = 30 * internal * factor;
@@ -1205,8 +1243,9 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32
        dib7000p_write_word(state, 143, 0);
 }
 
-static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_tune(struct dvb_frontend *demod)
 {
+       struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
        struct dib7000p_state *state = demod->demodulator_priv;
        u16 tmp = 0;
 
@@ -1239,7 +1278,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
 
        /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
        tmp = (6 << 8) | 0x80;
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                tmp |= (2 << 12);
                break;
@@ -1255,7 +1294,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
 
        /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
        tmp = (0 << 4);
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                tmp |= 0x6;
                break;
@@ -1271,7 +1310,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
 
        /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
        tmp = (0 << 4);
-       switch (ch->u.ofdm.transmission_mode) {
+       switch (ch->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                tmp |= 0x6;
                break;
@@ -1303,9 +1342,9 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
        }
 
        if (state->cfg.spur_protect)
-               dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+               dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
 
-       dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+       dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
        return 0;
 }
 
@@ -1323,7 +1362,7 @@ static int dib7000p_sleep(struct dvb_frontend *demod)
 {
        struct dib7000p_state *state = demod->demodulator_priv;
        if (state->version == SOC7090)
-               return dib7090_set_output_mode(demod, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+               return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
        return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
 }
 
@@ -1345,93 +1384,94 @@ static int dib7000p_identify(struct dib7000p_state *st)
        return 0;
 }
 
-static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7000p_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib7000p_state *state = fe->demodulator_priv;
        u16 tps = dib7000p_read_word(state, 463);
 
        fep->inversion = INVERSION_AUTO;
 
-       fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
+       fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
 
        switch ((tps >> 8) & 0x3) {
        case 0:
-               fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               fep->transmission_mode = TRANSMISSION_MODE_2K;
                break;
        case 1:
-               fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               fep->transmission_mode = TRANSMISSION_MODE_8K;
                break;
-       /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+       /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
        }
 
        switch (tps & 0x3) {
        case 0:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               fep->guard_interval = GUARD_INTERVAL_1_32;
                break;
        case 1:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               fep->guard_interval = GUARD_INTERVAL_1_16;
                break;
        case 2:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               fep->guard_interval = GUARD_INTERVAL_1_8;
                break;
        case 3:
-               fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               fep->guard_interval = GUARD_INTERVAL_1_4;
                break;
        }
 
        switch ((tps >> 14) & 0x3) {
        case 0:
-               fep->u.ofdm.constellation = QPSK;
+               fep->modulation = QPSK;
                break;
        case 1:
-               fep->u.ofdm.constellation = QAM_16;
+               fep->modulation = QAM_16;
                break;
        case 2:
        default:
-               fep->u.ofdm.constellation = QAM_64;
+               fep->modulation = QAM_64;
                break;
        }
 
        /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
        /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
 
-       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       fep->hierarchy = HIERARCHY_NONE;
        switch ((tps >> 5) & 0x7) {
        case 1:
-               fep->u.ofdm.code_rate_HP = FEC_1_2;
+               fep->code_rate_HP = FEC_1_2;
                break;
        case 2:
-               fep->u.ofdm.code_rate_HP = FEC_2_3;
+               fep->code_rate_HP = FEC_2_3;
                break;
        case 3:
-               fep->u.ofdm.code_rate_HP = FEC_3_4;
+               fep->code_rate_HP = FEC_3_4;
                break;
        case 5:
-               fep->u.ofdm.code_rate_HP = FEC_5_6;
+               fep->code_rate_HP = FEC_5_6;
                break;
        case 7:
        default:
-               fep->u.ofdm.code_rate_HP = FEC_7_8;
+               fep->code_rate_HP = FEC_7_8;
                break;
 
        }
 
        switch ((tps >> 2) & 0x7) {
        case 1:
-               fep->u.ofdm.code_rate_LP = FEC_1_2;
+               fep->code_rate_LP = FEC_1_2;
                break;
        case 2:
-               fep->u.ofdm.code_rate_LP = FEC_2_3;
+               fep->code_rate_LP = FEC_2_3;
                break;
        case 3:
-               fep->u.ofdm.code_rate_LP = FEC_3_4;
+               fep->code_rate_LP = FEC_3_4;
                break;
        case 5:
-               fep->u.ofdm.code_rate_LP = FEC_5_6;
+               fep->code_rate_LP = FEC_5_6;
                break;
        case 7:
        default:
-               fep->u.ofdm.code_rate_LP = FEC_7_8;
+               fep->code_rate_LP = FEC_7_8;
                break;
        }
 
@@ -1440,36 +1480,36 @@ static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa
        return 0;
 }
 
-static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7000p_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dib7000p_state *state = fe->demodulator_priv;
        int time, ret;
 
-       if (state->version == SOC7090) {
+       if (state->version == SOC7090)
                dib7090_set_diversity_in(fe, 0);
-               dib7090_set_output_mode(fe, OUTMODE_HIGH_Z);
-       } else
+       else
                dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
 
        /* maybe the parameter has been changed */
        state->sfn_workaround_active = buggy_sfn_workaround;
 
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, fep);
+               fe->ops.tuner_ops.set_params(fe);
 
        /* start up the AGC */
        state->agc_state = 0;
        do {
-               time = dib7000p_agc_startup(fe, fep);
+               time = dib7000p_agc_startup(fe);
                if (time != -1)
                        msleep(time);
        } while (time != -1);
 
-       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
-               fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+       if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
                int i = 800, found;
 
-               dib7000p_autosearch_start(fe, fep);
+               dib7000p_autosearch_start(fe);
                do {
                        msleep(1);
                        found = dib7000p_autosearch_is_irq(fe);
@@ -1479,15 +1519,19 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa
                if (found == 0 || found == 1)
                        return 0;
 
-               dib7000p_get_frontend(fe, fep);
+               dib7000p_get_frontend(fe);
        }
 
-       ret = dib7000p_tune(fe, fep);
+       ret = dib7000p_tune(fe);
 
        /* make this a config parameter */
-       if (state->version == SOC7090)
+       if (state->version == SOC7090) {
                dib7090_set_output_mode(fe, state->cfg.output_mode);
-       else
+               if (state->cfg.enMpegOutput == 0) {
+                       dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
+                       dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+               }
+       } else
                dib7000p_set_output_mode(state, state->cfg.output_mode);
 
        return ret;
@@ -1831,7 +1875,8 @@ static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg m
        return num;
 }
 
-int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num, u16 apb_address)
+static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num, u16 apb_address)
 {
        struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
        u16 word;
@@ -1933,10 +1978,10 @@ static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[]
                apb_address = 915;
                break;
        case 0x27:
-               apb_address = 916;
+               apb_address = 917;
                break;
        case 0x28:
-               apb_address = 917;
+               apb_address = 916;
                break;
        case 0x1d:
                i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
@@ -2031,12 +2076,7 @@ static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32
 
 static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
 {
-       u8 index_buf;
-       u16 rx_copy_buf[22];
-
        dprintk("Configure DibStream Tx");
-       for (index_buf = 0; index_buf < 22; index_buf++)
-               rx_copy_buf[index_buf] = dib7000p_read_word(state, 1536+index_buf);
 
        dib7000p_write_word(state, 1615, 1);
        dib7000p_write_word(state, 1603, P_Kin);
@@ -2048,9 +2088,6 @@ static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout
        dib7000p_write_word(state, 1612, syncSize);
        dib7000p_write_word(state, 1615, 0);
 
-       for (index_buf = 0; index_buf < 22; index_buf++)
-               dib7000p_write_word(state, 1536+index_buf, rx_copy_buf[index_buf]);
-
        return 0;
 }
 
@@ -2077,109 +2114,121 @@ static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout
        return 0;
 }
 
-static int dib7090_enDivOnHostBus(struct dib7000p_state *state)
-{
-       u16 reg;
-
-       dprintk("Enable Diversity on host bus");
-       reg = (1 << 8) | (1 << 5);
-       dib7000p_write_word(state, 1288, reg);
-
-       return dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
-}
-
-static int dib7090_enAdcOnHostBus(struct dib7000p_state *state)
-{
-       u16 reg;
-
-       dprintk("Enable ADC on host bus");
-       reg = (1 << 7) | (1 << 5);
-       dib7000p_write_word(state, 1288, reg);
-
-       return dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
-}
-
-static int dib7090_enMpegOnHostBus(struct dib7000p_state *state)
+static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
 {
-       u16 reg;
-
-       dprintk("Enable Mpeg on host bus");
-       reg = (1 << 9) | (1 << 5);
-       dib7000p_write_word(state, 1288, reg);
+       u16 reg_1287 = dib7000p_read_word(state, 1287);
 
-       return dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
-}
+       switch (onoff) {
+       case 1:
+                       reg_1287 &= ~(1<<7);
+                       break;
+       case 0:
+                       reg_1287 |= (1<<7);
+                       break;
+       }
 
-static int dib7090_enMpegInput(struct dib7000p_state *state)
-{
-       dprintk("Enable Mpeg input");
-       return dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);   /*outputRate = 8 */
+       dib7000p_write_word(state, 1287, reg_1287);
 }
 
-static int dib7090_enMpegMux(struct dib7000p_state *state, u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+static void dib7090_configMpegMux(struct dib7000p_state *state,
+               u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
 {
-       u16 reg = (1 << 7) | ((pulseWidth & 0x1f) << 2) | ((enSerialMode & 0x1) << 1) | (enSerialClkDiv2 & 0x1);
-
        dprintk("Enable Mpeg mux");
-       dib7000p_write_word(state, 1287, reg);
 
-       reg &= ~(1 << 7);
-       dib7000p_write_word(state, 1287, reg);
+       dib7090_enMpegMux(state, 0);
 
-       reg = (1 << 4);
-       dib7000p_write_word(state, 1288, reg);
+       /* If the input mode is MPEG do not divide the serial clock */
+       if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+               enSerialClkDiv2 = 0;
 
-       return 0;
+       dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
+                       | ((enSerialMode & 0x1) << 1)
+                       | (enSerialClkDiv2 & 0x1));
+
+       dib7090_enMpegMux(state, 1);
 }
 
-static int dib7090_disableMpegMux(struct dib7000p_state *state)
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
 {
-       u16 reg;
-
-       dprintk("Disable Mpeg mux");
-       dib7000p_write_word(state, 1288, 0);
-
-       reg = dib7000p_read_word(state, 1287);
-       reg &= ~(1 << 7);
-       dib7000p_write_word(state, 1287, reg);
+       u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
 
-       return 0;
+       switch (mode) {
+       case MPEG_ON_DIBTX:
+                       dprintk("SET MPEG ON DIBSTREAM TX");
+                       dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+                       reg_1288 |= (1<<9);
+                       break;
+       case DIV_ON_DIBTX:
+                       dprintk("SET DIV_OUT ON DIBSTREAM TX");
+                       dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+                       reg_1288 |= (1<<8);
+                       break;
+       case ADC_ON_DIBTX:
+                       dprintk("SET ADC_OUT ON DIBSTREAM TX");
+                       dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+                       reg_1288 |= (1<<7);
+                       break;
+       default:
+                       break;
+       }
+       dib7000p_write_word(state, 1288, reg_1288);
 }
 
-static int dib7090_set_input_mode(struct dvb_frontend *fe, int mode)
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
 {
-       struct dib7000p_state *state = fe->demodulator_priv;
+       u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
 
        switch (mode) {
-       case INPUT_MODE_DIVERSITY:
-                       dprintk("Enable diversity INPUT");
-                       dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+       case DEMOUT_ON_HOSTBUS:
+                       dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+                       dib7090_enMpegMux(state, 0);
+                       reg_1288 |= (1<<6);
+                       break;
+       case DIBTX_ON_HOSTBUS:
+                       dprintk("SET DIBSTREAM TX ON HOST BUS");
+                       dib7090_enMpegMux(state, 0);
+                       reg_1288 |= (1<<5);
                        break;
-       case INPUT_MODE_MPEG:
-                       dprintk("Enable Mpeg INPUT");
-                       dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
+       case MPEG_ON_HOSTBUS:
+                       dprintk("SET MPEG MUX ON HOST BUS");
+                       reg_1288 |= (1<<4);
                        break;
-       case INPUT_MODE_OFF:
        default:
-                       dprintk("Disable INPUT");
-                       dib7090_cfg_DibRx(state, 0, 0, 0, 0, 0, 0, 0);
                        break;
        }
-       return 0;
+       dib7000p_write_word(state, 1288, reg_1288);
 }
 
-static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
+int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
 {
+       struct dib7000p_state *state = fe->demodulator_priv;
+       u16 reg_1287;
+
        switch (onoff) {
-       case 0:         /* only use the internal way - not the diversity input */
-               dib7090_set_input_mode(fe, INPUT_MODE_MPEG);
-               break;
-       case 1:         /* both ways */
-       case 2:         /* only the diversity input */
-               dib7090_set_input_mode(fe, INPUT_MODE_DIVERSITY);
-               break;
+       case 0: /* only use the internal way - not the diversity input */
+                       dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
+                       dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+                       /* Do not divide the serial clock of MPEG MUX */
+                       /* in SERIAL MODE in case input mode MPEG is used */
+                       reg_1287 = dib7000p_read_word(state, 1287);
+                       /* enSerialClkDiv2 == 1 ? */
+                       if ((reg_1287 & 0x1) == 1) {
+                               /* force enSerialClkDiv2 = 0 */
+                               reg_1287 &= ~0x1;
+                               dib7000p_write_word(state, 1287, reg_1287);
+                       }
+                       state->input_mode_mpeg = 1;
+                       break;
+       case 1: /* both ways */
+       case 2: /* only the diversity input */
+                       dprintk("%s ON : Enable diversity INPUT", __func__);
+                       dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+                       state->input_mode_mpeg = 0;
+                       break;
        }
 
+       dib7000p_set_diversity_in(&state->demod, onoff);
        return 0;
 }
 
@@ -2204,69 +2253,63 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
 
        case OUTMODE_MPEG2_SERIAL:
                if (prefer_mpeg_mux_use) {
-                       dprintk("Sip 7090P setting output mode TS_SERIAL using Mpeg Mux");
-                       dib7090_enMpegOnHostBus(state);
-                       dib7090_enMpegInput(state);
-                       if (state->cfg.enMpegOutput == 1)
-                               dib7090_enMpegMux(state, 3, 1, 1);
-
-               } else {        /* Use Smooth block */
-                       dprintk("Sip 7090P setting output mode TS_SERIAL using Smooth bloc");
-                       dib7090_disableMpegMux(state);
-                       dib7000p_write_word(state, 1288, (1 << 6));
-                       outreg |= (2 << 6) | (0 << 1);
+                       dprintk("setting output mode TS_SERIAL using Mpeg Mux");
+                       dib7090_configMpegMux(state, 3, 1, 1);
+                       dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+               } else {/* Use Smooth block */
+                       dprintk("setting output mode TS_SERIAL using Smooth bloc");
+                       dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+                       outreg |= (2<<6) | (0 << 1);
                }
                break;
 
        case OUTMODE_MPEG2_PAR_GATED_CLK:
                if (prefer_mpeg_mux_use) {
-                       dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
-                       dib7090_enMpegOnHostBus(state);
-                       dib7090_enMpegInput(state);
-                       if (state->cfg.enMpegOutput == 1)
-                               dib7090_enMpegMux(state, 2, 0, 0);
-               } else {        /* Use Smooth block */
-                       dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Smooth block");
-                       dib7090_disableMpegMux(state);
-                       dib7000p_write_word(state, 1288, (1 << 6));
-                       outreg |= (0 << 6);
+                       dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+                       dib7090_configMpegMux(state, 2, 0, 0);
+                       dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+               } else { /* Use Smooth block */
+                       dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
+                       dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+                       outreg |= (0<<6);
                }
                break;
 
        case OUTMODE_MPEG2_PAR_CONT_CLK:        /* Using Smooth block only */
-               dprintk("Sip 7090P setting output mode TS_PARALLEL_CONT using Smooth block");
-               dib7090_disableMpegMux(state);
-               dib7000p_write_word(state, 1288, (1 << 6));
-               outreg |= (1 << 6);
+               dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
+               dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+               outreg |= (1<<6);
                break;
 
        case OUTMODE_MPEG2_FIFO:        /* Using Smooth block because not supported by new Mpeg Mux bloc */
-               dprintk("Sip 7090P setting output mode TS_FIFO using Smooth block");
-               dib7090_disableMpegMux(state);
-               dib7000p_write_word(state, 1288, (1 << 6));
-               outreg |= (5 << 6);
+               dprintk("setting output mode TS_FIFO using Smooth block");
+               dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+               outreg |= (5<<6);
                smo_mode |= (3 << 1);
                fifo_threshold = 512;
                break;
 
        case OUTMODE_DIVERSITY:
-               dprintk("Sip 7090P setting output mode MODE_DIVERSITY");
-               dib7090_disableMpegMux(state);
-               dib7090_enDivOnHostBus(state);
+               dprintk("setting output mode MODE_DIVERSITY");
+               dib7090_setDibTxMux(state, DIV_ON_DIBTX);
+               dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
                break;
 
        case OUTMODE_ANALOG_ADC:
-               dprintk("Sip 7090P setting output mode MODE_ANALOG_ADC");
-               dib7090_enAdcOnHostBus(state);
+               dprintk("setting output mode MODE_ANALOG_ADC");
+               dib7090_setDibTxMux(state, ADC_ON_DIBTX);
+               dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
                break;
        }
+       if (mode != OUTMODE_HIGH_Z)
+               outreg |= (1 << 10);
 
        if (state->cfg.output_mpeg2_in_188_bytes)
                smo_mode |= (1 << 5);
 
        ret |= dib7000p_write_word(state, 235, smo_mode);
        ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
-       ret |= dib7000p_write_word(state, 1286, outreg | (1 << 10));    /* allways set Dout active = 1 !!! */
+       ret |= dib7000p_write_word(state, 1286, outreg);
 
        return ret;
 }
@@ -2296,13 +2339,6 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
 }
 EXPORT_SYMBOL(dib7090_tuner_sleep);
 
-int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
-{
-       dprintk("AGC restart callback: %d", restart);
-       return 0;
-}
-EXPORT_SYMBOL(dib7090_agc_restart);
-
 int dib7090_get_adc_power(struct dvb_frontend *fe)
 {
        return dib7000p_get_adc_power(fe);
@@ -2391,9 +2427,9 @@ error:
 EXPORT_SYMBOL(dib7000p_attach);
 
 static struct dvb_frontend_ops dib7000p_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                 .name = "DiBcom 7000PC",
-                .type = FE_OFDM,
                 .frequency_min = 44250000,
                 .frequency_max = 867250000,
                 .frequency_stepsize = 62500,
index 0179f9474bac050054c2842626edb97697e53b6f..b61b03a6e1edad8480005dccb5817f662e0c0253 100644 (file)
@@ -56,11 +56,12 @@ extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
 extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
 extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
 extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart);
 extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
 extern int dib7090_get_adc_power(struct dvb_frontend *fe);
 extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
 extern int dib7090_slave_reset(struct dvb_frontend *fe);
+extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+               u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
 #else
 static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
@@ -122,12 +123,6 @@ static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
        return 0;
 }
 
-static inline int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return -ENODEV;
-}
-
 static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
@@ -151,6 +146,13 @@ static inline int dib7090_slave_reset(struct dvb_frontend *fe)
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return -ENODEV;
 }
+
+static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
+               u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
 #endif
 
 #endif
index fe284d5292f5422f16a846e1077c7df34c576098..9ca34f495009dc29f15509f9075986af3247fe48 100644 (file)
@@ -81,11 +81,15 @@ struct dib8000_state {
        u8 i2c_write_buffer[4];
        u8 i2c_read_buffer[2];
        struct mutex i2c_buffer_lock;
+       u8 input_mode_mpeg;
+
+       u16 tuner_enable;
+       struct i2c_adapter dib8096p_tuner_adap;
 };
 
 enum dib8000_power_mode {
-       DIB8000M_POWER_ALL = 0,
-       DIB8000M_POWER_INTERFACE_ONLY,
+       DIB8000_POWER_ALL = 0,
+       DIB8000_POWER_INTERFACE_ONLY,
 };
 
 static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
@@ -428,20 +432,31 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow
        /* by default everything is going to be powered off */
        u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
                reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
+               reg_1280;
+
+       if (state->revision != 0x8090)
                reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
+       else
+               reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
 
        /* now, depending on the requested mode, we power on */
        switch (mode) {
                /* power up everything in the demod */
-       case DIB8000M_POWER_ALL:
+       case DIB8000_POWER_ALL:
                reg_774 = 0x0000;
                reg_775 = 0x0000;
                reg_776 = 0x0000;
                reg_900 &= 0xfffc;
-               reg_1280 &= 0x00ff;
+               if (state->revision != 0x8090)
+                       reg_1280 &= 0x00ff;
+               else
+                       reg_1280 &= 0x707f;
                break;
-       case DIB8000M_POWER_INTERFACE_ONLY:
-               reg_1280 &= 0x00ff;
+       case DIB8000_POWER_INTERFACE_ONLY:
+               if (state->revision != 0x8090)
+                       reg_1280 &= 0x00ff;
+               else
+                       reg_1280 &= 0xfa7b;
                break;
        }
 
@@ -453,19 +468,67 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow
        dib8000_write_word(state, 1280, reg_1280);
 }
 
+static int dib8000_init_sdram(struct dib8000_state *state)
+{
+       u16 reg = 0;
+       dprintk("Init sdram");
+
+       reg = dib8000_read_word(state, 274)&0xfff0;
+       /* P_dintlv_delay_ram = 7 because of MobileSdram */
+       dib8000_write_word(state, 274, reg | 0x7);
+
+       dib8000_write_word(state, 1803, (7<<2));
+
+       reg = dib8000_read_word(state, 1280);
+       /* force restart P_restart_sdram */
+       dib8000_write_word(state, 1280,  reg | (1<<2));
+
+       /* release restart P_restart_sdram */
+       dib8000_write_word(state, 1280,  reg);
+
+       return 0;
+}
+
 static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
 {
        int ret = 0;
-       u16 reg_907 = dib8000_read_word(state, 907), reg_908 = dib8000_read_word(state, 908);
+       u16 reg, reg_907 = dib8000_read_word(state, 907);
+       u16 reg_908 = dib8000_read_word(state, 908);
 
        switch (no) {
        case DIBX000_SLOW_ADC_ON:
-               reg_908 |= (1 << 1) | (1 << 0);
-               ret |= dib8000_write_word(state, 908, reg_908);
-               reg_908 &= ~(1 << 1);
+               if (state->revision != 0x8090) {
+                       reg_908 |= (1 << 1) | (1 << 0);
+                       ret |= dib8000_write_word(state, 908, reg_908);
+                       reg_908 &= ~(1 << 1);
+               } else {
+                       reg = dib8000_read_word(state, 1925);
+                       /* en_slowAdc = 1 & reset_sladc = 1 */
+                       dib8000_write_word(state, 1925, reg |
+                                       (1<<4) | (1<<2));
+
+                       /* read acces to make it works... strange ... */
+                       reg = dib8000_read_word(state, 1925);
+                       msleep(20);
+                       /* en_slowAdc = 1 & reset_sladc = 0 */
+                       dib8000_write_word(state, 1925, reg & ~(1<<4));
+
+                       reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
+                                       | (0x3 << 12));
+                       /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
+                          (Vin2 = Vcm) */
+                       dib8000_write_word(state, 921, reg | (1 << 14)
+                                       | (3 << 12));
+               }
                break;
 
        case DIBX000_SLOW_ADC_OFF:
+               if (state->revision == 0x8090) {
+                       reg = dib8000_read_word(state, 1925);
+                       /* reset_sladc = 1 en_slowAdc = 0 */
+                       dib8000_write_word(state, 1925,
+                                       (reg & ~(1<<2)) | (1<<4));
+               }
                reg_908 |= (1 << 1) | (1 << 0);
                break;
 
@@ -521,7 +584,12 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
 
 static int dib8000_sad_calib(struct dib8000_state *state)
 {
-/* internal */
+       if (state->revision == 0x8090) {
+               dprintk("%s: the sad calibration is not needed for the dib8096P",
+                               __func__);
+               return 0;
+       }
+       /* internal */
        dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
        dib8000_write_word(state, 924, 776);    // 0.625*3.3 / 4096
 
@@ -546,48 +614,129 @@ EXPORT_SYMBOL(dib8000_set_wbd_ref);
 static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
 {
        dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
-       dib8000_write_word(state, 23, (u16) (((bw->internal * 1000) >> 16) & 0xffff));  /* P_sec_len */
-       dib8000_write_word(state, 24, (u16) ((bw->internal * 1000) & 0xffff));
+       if (state->revision != 0x8090) {
+               dib8000_write_word(state, 23,
+                               (u16) (((bw->internal * 1000) >> 16) & 0xffff));
+               dib8000_write_word(state, 24,
+                               (u16) ((bw->internal * 1000) & 0xffff));
+       } else {
+               dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
+               dib8000_write_word(state, 24,
+                               (u16) ((bw->internal  / 2 * 1000) & 0xffff));
+       }
        dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
        dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
        dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
 
-       dib8000_write_word(state, 922, bw->sad_cfg);
+       if (state->revision != 0x8090)
+               dib8000_write_word(state, 922, bw->sad_cfg);
 }
 
 static void dib8000_reset_pll(struct dib8000_state *state)
 {
        const struct dibx000_bandwidth_config *pll = state->cfg.pll;
-       u16 clk_cfg1;
-
-       // clk_cfg0
-       dib8000_write_word(state, 901, (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
-
-       // clk_cfg1
-       clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
-               (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) |
-               (pll->pll_range << 1) | (pll->pll_reset << 0);
-
-       dib8000_write_word(state, 902, clk_cfg1);
-       clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
-       dib8000_write_word(state, 902, clk_cfg1);
-
-       dprintk("clk_cfg1: 0x%04x", clk_cfg1);  /* 0x507 1 0 1 000 0 0 11 1 */
-
-       /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
-       if (state->cfg.pll->ADClkSrc == 0)
-               dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) |
-                               (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
-       else if (state->cfg.refclksel != 0)
-               dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
-                               ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) |
-                               (pll->ADClkSrc << 7) | (0 << 1));
-       else
-               dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
+       u16 clk_cfg1, reg;
+
+       if (state->revision != 0x8090) {
+               dib8000_write_word(state, 901,
+                               (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
+
+               clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
+                       (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
+                       (1 << 3) | (pll->pll_range << 1) |
+                       (pll->pll_reset << 0);
+
+               dib8000_write_word(state, 902, clk_cfg1);
+               clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
+               dib8000_write_word(state, 902, clk_cfg1);
+
+               dprintk("clk_cfg1: 0x%04x", clk_cfg1);
+
+               /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
+               if (state->cfg.pll->ADClkSrc == 0)
+                       dib8000_write_word(state, 904,
+                                       (0 << 15) | (0 << 12) | (0 << 10) |
+                                       (pll->modulo << 8) |
+                                       (pll->ADClkSrc << 7) | (0 << 1));
+               else if (state->cfg.refclksel != 0)
+                       dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+                                       ((state->cfg.refclksel & 0x3) << 10) |
+                                       (pll->modulo << 8) |
+                                       (pll->ADClkSrc << 7) | (0 << 1));
+               else
+                       dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+                                       (3 << 10) | (pll->modulo << 8) |
+                                       (pll->ADClkSrc << 7) | (0 << 1));
+       } else {
+               dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
+                               (pll->pll_range<<12) | (pll->pll_ratio<<6) |
+                               (pll->pll_prediv));
+
+               reg = dib8000_read_word(state, 1857);
+               dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
+
+               reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
+               dib8000_write_word(state, 1858, reg | 1);
+
+               dib8000_write_word(state, 904, (pll->modulo << 8));
+       }
 
        dib8000_reset_pll_common(state, pll);
 }
 
+int dib8000_update_pll(struct dvb_frontend *fe,
+               struct dibx000_bandwidth_config *pll)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+       u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
+       u8 loopdiv, prediv;
+       u32 internal, xtal;
+
+       /* get back old values */
+       prediv = reg_1856 & 0x3f;
+       loopdiv = (reg_1856 >> 6) & 0x3f;
+
+       if ((pll != NULL) && (pll->pll_prediv != prediv ||
+                               pll->pll_ratio != loopdiv)) {
+               dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+               reg_1856 &= 0xf000;
+               reg_1857 = dib8000_read_word(state, 1857);
+               /* disable PLL */
+               dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
+
+               dib8000_write_word(state, 1856, reg_1856 |
+                               ((pll->pll_ratio & 0x3f) << 6) |
+                               (pll->pll_prediv & 0x3f));
+
+               /* write new system clk into P_sec_len */
+               internal = dib8000_read32(state, 23) / 1000;
+               dprintk("Old Internal = %d", internal);
+               xtal = 2 * (internal / loopdiv) * prediv;
+               internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
+               dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
+               dprintk("New Internal = %d", internal);
+
+               dib8000_write_word(state, 23,
+                               (u16) (((internal / 2) >> 16) & 0xffff));
+               dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
+               /* enable PLL */
+               dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
+
+               while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
+                       dprintk("Waiting for PLL to lock");
+
+               /* verify */
+               reg_1856 = dib8000_read_word(state, 1856);
+               dprintk("PLL Updated with prediv = %d and loopdiv = %d",
+                               reg_1856&0x3f, (reg_1856>>6)&0x3f);
+
+               return 0;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(dib8000_update_pll);
+
+
 static int dib8000_reset_gpio(struct dib8000_state *st)
 {
        /* reset the GPIOs */
@@ -721,9 +870,6 @@ static const u16 dib8000_defaults[] = {
                (3 << 5) |              /* P_ctrl_pre_freq_step=3 */
                (1 << 0),               /* P_pre_freq_win_len=1 */
 
-       1, 903,
-       (0 << 4) | 2,           // P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW)
-
        0,
 };
 
@@ -740,7 +886,8 @@ static u16 dib8000_identify(struct i2c_device *client)
        }
 
        value = dib8000_i2c_read16(client, 897);
-       if (value != 0x8000 && value != 0x8001 && value != 0x8002) {
+       if (value != 0x8000 && value != 0x8001 &&
+                       value != 0x8002 && value != 0x8090) {
                dprintk("wrong Device ID (%x)", value);
                return 0;
        }
@@ -755,6 +902,9 @@ static u16 dib8000_identify(struct i2c_device *client)
        case 0x8002:
                dprintk("found DiB8000C");
                break;
+       case 0x8090:
+               dprintk("found DiB8096P");
+               break;
        }
        return value;
 }
@@ -763,17 +913,19 @@ static int dib8000_reset(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
 
-       dib8000_write_word(state, 1287, 0x0003);        /* sram lead in, rdy */
-
        if ((state->revision = dib8000_identify(&state->i2c)) == 0)
                return -EINVAL;
 
+       /* sram lead in, rdy */
+       if (state->revision != 0x8090)
+               dib8000_write_word(state, 1287, 0x0003);
+
        if (state->revision == 0x8000)
                dprintk("error : dib8000 MA not supported");
 
        dibx000_reset_i2c_master(&state->i2c_master);
 
-       dib8000_set_power_mode(state, DIB8000M_POWER_ALL);
+       dib8000_set_power_mode(state, DIB8000_POWER_ALL);
 
        /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
        dib8000_set_adc_state(state, DIBX000_VBG_ENABLE);
@@ -782,8 +934,10 @@ static int dib8000_reset(struct dvb_frontend *fe)
        dib8000_write_word(state, 770, 0xffff);
        dib8000_write_word(state, 771, 0xffff);
        dib8000_write_word(state, 772, 0xfffc);
-       dib8000_write_word(state, 898, 0x000c); // sad
-       dib8000_write_word(state, 1280, 0x004d);
+       if (state->revision == 0x8090)
+               dib8000_write_word(state, 1280, 0x0045);
+       else
+               dib8000_write_word(state, 1280, 0x004d);
        dib8000_write_word(state, 1281, 0x000c);
 
        dib8000_write_word(state, 770, 0x0000);
@@ -794,19 +948,25 @@ static int dib8000_reset(struct dvb_frontend *fe)
        dib8000_write_word(state, 1281, 0x0000);
 
        /* drives */
-       if (state->cfg.drives)
-               dib8000_write_word(state, 906, state->cfg.drives);
-       else {
-               dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
-               dib8000_write_word(state, 906, 0x2d98); // min drive SDRAM - not optimal - adjust
+       if (state->revision != 0x8090) {
+               if (state->cfg.drives)
+                       dib8000_write_word(state, 906, state->cfg.drives);
+               else {
+                       dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
+                       /* min drive SDRAM - not optimal - adjust */
+                       dib8000_write_word(state, 906, 0x2d98);
+               }
        }
 
        dib8000_reset_pll(state);
+       if (state->revision != 0x8090)
+               dib8000_write_word(state, 898, 0x0004);
 
        if (dib8000_reset_gpio(state) != 0)
                dprintk("GPIO reset was not successful.");
 
-       if (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)
+       if ((state->revision != 0x8090) &&
+                       (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
                dprintk("OUTPUT_MODE could not be resetted.");
 
        state->current_agc = NULL;
@@ -832,6 +992,8 @@ static int dib8000_reset(struct dvb_frontend *fe)
                        l = *n++;
                }
        }
+       if (state->revision != 0x8090)
+               dib8000_write_word(state, 903, (0 << 4) | 2);
        state->isdbt_cfg_loaded = 0;
 
        //div_cfg override for special configs
@@ -844,10 +1006,12 @@ static int dib8000_reset(struct dvb_frontend *fe)
        dib8000_set_bandwidth(fe, 6000);
 
        dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-       dib8000_sad_calib(state);
-       dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+       if (state->revision != 0x8090) {
+               dib8000_sad_calib(state);
+               dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+       }
 
-       dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY);
+       dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
 
        return 0;
 }
@@ -879,6 +1043,8 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
 {
        struct dibx000_agc_config *agc = NULL;
        int i;
+       u16 reg;
+
        if (state->current_band == band && state->current_agc != NULL)
                return 0;
        state->current_band = band;
@@ -914,6 +1080,12 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
                dib8000_write_word(state, 106, state->wbd_ref);
        else                    // use default
                dib8000_write_word(state, 106, agc->wbd_ref);
+
+       if (state->revision == 0x8090) {
+               reg = dib8000_read_word(state, 922) & (0x3 << 2);
+               dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
+       }
+
        dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
        dib8000_write_word(state, 108, agc->agc1_max);
        dib8000_write_word(state, 109, agc->agc1_min);
@@ -925,7 +1097,10 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
        dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
 
        dib8000_write_word(state, 75, agc->agc1_pt3);
-       dib8000_write_word(state, 923, (dib8000_read_word(state, 923) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));   /*LB : 929 -> 923 */
+       if (state->revision != 0x8090)
+               dib8000_write_word(state, 923,
+                               (dib8000_read_word(state, 923) & 0xffe3) |
+                               (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
 
        return 0;
 }
@@ -968,14 +1143,30 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
        enum frontend_tune_state *tune_state = &state->tune_state;
-
        int ret = 0;
+       u16 reg, upd_demod_gain_period = 0x8000;
 
        switch (*tune_state) {
        case CT_AGC_START:
                // set power-up level: interf+analog+AGC
 
-               dib8000_set_adc_state(state, DIBX000_ADC_ON);
+               if (state->revision != 0x8090)
+                       dib8000_set_adc_state(state, DIBX000_ADC_ON);
+               else {
+                       dib8000_set_power_mode(state, DIB8000_POWER_ALL);
+
+                       reg = dib8000_read_word(state, 1947)&0xff00;
+                       dib8000_write_word(state, 1946,
+                                       upd_demod_gain_period & 0xFFFF);
+                       /* bit 14 = enDemodGain */
+                       dib8000_write_word(state, 1947, reg | (1<<14) |
+                                       ((upd_demod_gain_period >> 16) & 0xFF));
+
+                       /* enable adc i & q */
+                       reg = dib8000_read_word(state, 1920);
+                       dib8000_write_word(state, 1920, (reg | 0x3) &
+                                       (~(1 << 7)));
+               }
 
                if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
                        *tune_state = CT_AGC_STOP;
@@ -1026,6 +1217,579 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
 
 }
 
+static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
+{
+       u16 reg;
+
+       drive &= 0x7;
+
+       /* drive host bus 2, 3, 4 */
+       reg = dib8000_read_word(state, 1798) &
+               ~(0x7 | (0x7 << 6) | (0x7 << 12));
+       reg |= (drive<<12) | (drive<<6) | drive;
+       dib8000_write_word(state, 1798, reg);
+
+       /* drive host bus 5,6 */
+       reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
+       reg |= (drive<<8) | (drive<<2);
+       dib8000_write_word(state, 1799, reg);
+
+       /* drive host bus 7, 8, 9 */
+       reg = dib8000_read_word(state, 1800) &
+               ~(0x7 | (0x7 << 6) | (0x7 << 12));
+       reg |= (drive<<12) | (drive<<6) | drive;
+       dib8000_write_word(state, 1800, reg);
+
+       /* drive host bus 10, 11 */
+       reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
+       reg |= (drive<<8) | (drive<<2);
+       dib8000_write_word(state, 1801, reg);
+
+       /* drive host bus 12, 13, 14 */
+       reg = dib8000_read_word(state, 1802) &
+               ~(0x7 | (0x7 << 6) | (0x7 << 12));
+       reg |= (drive<<12) | (drive<<6) | drive;
+       dib8000_write_word(state, 1802, reg);
+}
+
+static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
+               u32 insertExtSynchro, u32 syncSize)
+{
+       u32 quantif = 3;
+       u32 nom = (insertExtSynchro * P_Kin+syncSize);
+       u32 denom = P_Kout;
+       u32 syncFreq = ((nom << quantif) / denom);
+
+       if ((syncFreq & ((1 << quantif) - 1)) != 0)
+               syncFreq = (syncFreq >> quantif) + 1;
+       else
+               syncFreq = (syncFreq >> quantif);
+
+       if (syncFreq != 0)
+               syncFreq = syncFreq - 1;
+
+       return syncFreq;
+}
+
+static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
+               u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
+               u32 syncWord, u32 syncSize)
+{
+       dprintk("Configure DibStream Tx");
+
+       dib8000_write_word(state, 1615, 1);
+       dib8000_write_word(state, 1603, P_Kin);
+       dib8000_write_word(state, 1605, P_Kout);
+       dib8000_write_word(state, 1606, insertExtSynchro);
+       dib8000_write_word(state, 1608, synchroMode);
+       dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
+       dib8000_write_word(state, 1610, syncWord & 0xffff);
+       dib8000_write_word(state, 1612, syncSize);
+       dib8000_write_word(state, 1615, 0);
+}
+
+static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
+               u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
+               u32 syncWord, u32 syncSize, u32 dataOutRate)
+{
+       u32 syncFreq;
+
+       dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
+
+       if ((P_Kin != 0) && (P_Kout != 0)) {
+               syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
+                               insertExtSynchro, syncSize);
+               dib8000_write_word(state, 1542, syncFreq);
+       }
+
+       dib8000_write_word(state, 1554, 1);
+       dib8000_write_word(state, 1536, P_Kin);
+       dib8000_write_word(state, 1537, P_Kout);
+       dib8000_write_word(state, 1539, synchroMode);
+       dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
+       dib8000_write_word(state, 1541, syncWord & 0xffff);
+       dib8000_write_word(state, 1543, syncSize);
+       dib8000_write_word(state, 1544, dataOutRate);
+       dib8000_write_word(state, 1554, 0);
+}
+
+static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
+{
+       u16 reg_1287;
+
+       reg_1287 = dib8000_read_word(state, 1287);
+
+       switch (onoff) {
+       case 1:
+                       reg_1287 &= ~(1 << 8);
+                       break;
+       case 0:
+                       reg_1287 |= (1 << 8);
+                       break;
+       }
+
+       dib8000_write_word(state, 1287, reg_1287);
+}
+
+static void dib8096p_configMpegMux(struct dib8000_state *state,
+               u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+{
+       u16 reg_1287;
+
+       dprintk("Enable Mpeg mux");
+
+       dib8096p_enMpegMux(state, 0);
+
+       /* If the input mode is MPEG do not divide the serial clock */
+       if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+               enSerialClkDiv2 = 0;
+
+       reg_1287 = ((pulseWidth & 0x1f) << 3) |
+               ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
+       dib8000_write_word(state, 1287, reg_1287);
+
+       dib8096p_enMpegMux(state, 1);
+}
+
+static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
+{
+       u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
+
+       switch (mode) {
+       case MPEG_ON_DIBTX:
+                       dprintk("SET MPEG ON DIBSTREAM TX");
+                       dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+                       reg_1288 |= (1 << 9); break;
+       case DIV_ON_DIBTX:
+                       dprintk("SET DIV_OUT ON DIBSTREAM TX");
+                       dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+                       reg_1288 |= (1 << 8); break;
+       case ADC_ON_DIBTX:
+                       dprintk("SET ADC_OUT ON DIBSTREAM TX");
+                       dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+                       reg_1288 |= (1 << 7); break;
+       default:
+                       break;
+       }
+       dib8000_write_word(state, 1288, reg_1288);
+}
+
+static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
+{
+       u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
+
+       switch (mode) {
+       case DEMOUT_ON_HOSTBUS:
+                       dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+                       dib8096p_enMpegMux(state, 0);
+                       reg_1288 |= (1 << 6);
+                       break;
+       case DIBTX_ON_HOSTBUS:
+                       dprintk("SET DIBSTREAM TX ON HOST BUS");
+                       dib8096p_enMpegMux(state, 0);
+                       reg_1288 |= (1 << 5);
+                       break;
+       case MPEG_ON_HOSTBUS:
+                       dprintk("SET MPEG MUX ON HOST BUS");
+                       reg_1288 |= (1 << 4);
+                       break;
+       default:
+                       break;
+       }
+       dib8000_write_word(state, 1288, reg_1288);
+}
+
+static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+       u16 reg_1287;
+
+       switch (onoff) {
+       case 0: /* only use the internal way - not the diversity input */
+                       dprintk("%s mode OFF : by default Enable Mpeg INPUT",
+                                       __func__);
+                       /* outputRate = 8 */
+                       dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+                       /* Do not divide the serial clock of MPEG MUX in
+                          SERIAL MODE in case input mode MPEG is used */
+                       reg_1287 = dib8000_read_word(state, 1287);
+                       /* enSerialClkDiv2 == 1 ? */
+                       if ((reg_1287 & 0x1) == 1) {
+                               /* force enSerialClkDiv2 = 0 */
+                               reg_1287 &= ~0x1;
+                               dib8000_write_word(state, 1287, reg_1287);
+                       }
+                       state->input_mode_mpeg = 1;
+                       break;
+       case 1: /* both ways */
+       case 2: /* only the diversity input */
+                       dprintk("%s ON : Enable diversity INPUT", __func__);
+                       dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+                       state->input_mode_mpeg = 0;
+                       break;
+       }
+
+       dib8000_set_diversity_in(state->fe[0], onoff);
+       return 0;
+}
+
+static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+       u16 outreg, smo_mode, fifo_threshold;
+       u8 prefer_mpeg_mux_use = 1;
+       int ret = 0;
+
+       dib8096p_host_bus_drive(state, 1);
+
+       fifo_threshold = 1792;
+       smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
+       outreg   = dib8000_read_word(state, 1286) &
+               ~((1 << 10) | (0x7 << 6) | (1 << 1));
+
+       switch (mode) {
+       case OUTMODE_HIGH_Z:
+                       outreg = 0;
+                       break;
+
+       case OUTMODE_MPEG2_SERIAL:
+                       if (prefer_mpeg_mux_use) {
+                               dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
+                               dib8096p_configMpegMux(state, 3, 1, 1);
+                               dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+                       } else {/* Use Smooth block */
+                               dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
+                               dib8096p_setHostBusMux(state,
+                                               DEMOUT_ON_HOSTBUS);
+                               outreg |= (2 << 6) | (0 << 1);
+                       }
+                       break;
+
+       case OUTMODE_MPEG2_PAR_GATED_CLK:
+                       if (prefer_mpeg_mux_use) {
+                               dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+                               dib8096p_configMpegMux(state, 2, 0, 0);
+                               dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+                       } else { /* Use Smooth block */
+                               dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
+                               dib8096p_setHostBusMux(state,
+                                               DEMOUT_ON_HOSTBUS);
+                               outreg |= (0 << 6);
+                       }
+                       break;
+
+       case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
+                       dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
+                       dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+                       outreg |= (1 << 6);
+                       break;
+
+       case OUTMODE_MPEG2_FIFO:
+                       /* Using Smooth block because not supported
+                          by new Mpeg Mux bloc */
+                       dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
+                       dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+                       outreg |= (5 << 6);
+                       smo_mode |= (3 << 1);
+                       fifo_threshold = 512;
+                       break;
+
+       case OUTMODE_DIVERSITY:
+                       dprintk("dib8096P setting output mode MODE_DIVERSITY");
+                       dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
+                       dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+                       break;
+
+       case OUTMODE_ANALOG_ADC:
+                       dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
+                       dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
+                       dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+                       break;
+       }
+
+       if (mode != OUTMODE_HIGH_Z)
+               outreg |= (1<<10);
+
+       dprintk("output_mpeg2_in_188_bytes = %d",
+                       state->cfg.output_mpeg2_in_188_bytes);
+       if (state->cfg.output_mpeg2_in_188_bytes)
+               smo_mode |= (1 << 5);
+
+       ret |= dib8000_write_word(state, 299, smo_mode);
+       /* synchronous fread */
+       ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
+       ret |= dib8000_write_word(state, 1286, outreg);
+
+       return ret;
+}
+
+static int map_addr_to_serpar_number(struct i2c_msg *msg)
+{
+       if (msg->buf[0] <= 15)
+               msg->buf[0] -= 1;
+       else if (msg->buf[0] == 17)
+               msg->buf[0] = 15;
+       else if (msg->buf[0] == 16)
+               msg->buf[0] = 17;
+       else if (msg->buf[0] == 19)
+               msg->buf[0] = 16;
+       else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
+               msg->buf[0] -= 3;
+       else if (msg->buf[0] == 28)
+               msg->buf[0] = 23;
+       else if (msg->buf[0] == 99)
+               msg->buf[0] = 99;
+       else
+               return -EINVAL;
+       return 0;
+}
+
+static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num)
+{
+       struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+       u8 n_overflow = 1;
+       u16 i = 1000;
+       u16 serpar_num = msg[0].buf[0];
+
+       while (n_overflow == 1 && i) {
+               n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+               i--;
+               if (i == 0)
+                       dprintk("Tuner ITF: write busy (overflow)");
+       }
+       dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
+       dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
+
+       return num;
+}
+
+static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num)
+{
+       struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+       u8 n_overflow = 1, n_empty = 1;
+       u16 i = 1000;
+       u16 serpar_num = msg[0].buf[0];
+       u16 read_word;
+
+       while (n_overflow == 1 && i) {
+               n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+               i--;
+               if (i == 0)
+                       dprintk("TunerITF: read busy (overflow)");
+       }
+       dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
+
+       i = 1000;
+       while (n_empty == 1 && i) {
+               n_empty = dib8000_read_word(state, 1984)&0x1;
+               i--;
+               if (i == 0)
+                       dprintk("TunerITF: read busy (empty)");
+       }
+
+       read_word = dib8000_read_word(state, 1987);
+       msg[1].buf[0] = (read_word >> 8) & 0xff;
+       msg[1].buf[1] = (read_word) & 0xff;
+
+       return num;
+}
+
+static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num)
+{
+       if (map_addr_to_serpar_number(&msg[0]) == 0) {
+               if (num == 1) /* write */
+                       return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
+               else /* read */
+                       return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
+       }
+       return num;
+}
+
+static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num, u16 apb_address)
+{
+       struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+       u16 word;
+
+       if (num == 1) {         /* write */
+               dib8000_write_word(state, apb_address,
+                               ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
+       } else {
+               word = dib8000_read_word(state, apb_address);
+               msg[1].buf[0] = (word >> 8) & 0xff;
+               msg[1].buf[1] = (word) & 0xff;
+       }
+       return num;
+}
+
+static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
+               struct i2c_msg msg[], int num)
+{
+       struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+       u16 apb_address = 0, word;
+       int i = 0;
+
+       switch (msg[0].buf[0]) {
+       case 0x12:
+                       apb_address = 1920;
+                       break;
+       case 0x14:
+                       apb_address = 1921;
+                       break;
+       case 0x24:
+                       apb_address = 1922;
+                       break;
+       case 0x1a:
+                       apb_address = 1923;
+                       break;
+       case 0x22:
+                       apb_address = 1924;
+                       break;
+       case 0x33:
+                       apb_address = 1926;
+                       break;
+       case 0x34:
+                       apb_address = 1927;
+                       break;
+       case 0x35:
+                       apb_address = 1928;
+                       break;
+       case 0x36:
+                       apb_address = 1929;
+                       break;
+       case 0x37:
+                       apb_address = 1930;
+                       break;
+       case 0x38:
+                       apb_address = 1931;
+                       break;
+       case 0x39:
+                       apb_address = 1932;
+                       break;
+       case 0x2a:
+                       apb_address = 1935;
+                       break;
+       case 0x2b:
+                       apb_address = 1936;
+                       break;
+       case 0x2c:
+                       apb_address = 1937;
+                       break;
+       case 0x2d:
+                       apb_address = 1938;
+                       break;
+       case 0x2e:
+                       apb_address = 1939;
+                       break;
+       case 0x2f:
+                       apb_address = 1940;
+                       break;
+       case 0x30:
+                       apb_address = 1941;
+                       break;
+       case 0x31:
+                       apb_address = 1942;
+                       break;
+       case 0x32:
+                       apb_address = 1943;
+                       break;
+       case 0x3e:
+                       apb_address = 1944;
+                       break;
+       case 0x3f:
+                       apb_address = 1945;
+                       break;
+       case 0x40:
+                       apb_address = 1948;
+                       break;
+       case 0x25:
+                       apb_address = 936;
+                       break;
+       case 0x26:
+                       apb_address = 937;
+                       break;
+       case 0x27:
+                       apb_address = 938;
+                       break;
+       case 0x28:
+                       apb_address = 939;
+                       break;
+       case 0x1d:
+                       /* get sad sel request */
+                       i = ((dib8000_read_word(state, 921) >> 12)&0x3);
+                       word = dib8000_read_word(state, 924+i);
+                       msg[1].buf[0] = (word >> 8) & 0xff;
+                       msg[1].buf[1] = (word) & 0xff;
+                       return num;
+       case 0x1f:
+                       if (num == 1) { /* write */
+                               word = (u16) ((msg[0].buf[1] << 8) |
+                                               msg[0].buf[2]);
+                               /* in the VGAMODE Sel are located on bit 0/1 */
+                               word &= 0x3;
+                               word = (dib8000_read_word(state, 921) &
+                                               ~(3<<12)) | (word<<12);
+                               /* Set the proper input */
+                               dib8000_write_word(state, 921, word);
+                               return num;
+                       }
+       }
+
+       if (apb_address != 0) /* R/W acces via APB */
+               return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
+       else  /* R/W access via SERPAR  */
+               return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
+
+       return 0;
+}
+
+static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
+       .master_xfer = dib8096p_tuner_xfer,
+       .functionality = dib8096p_i2c_func,
+};
+
+struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+       struct dib8000_state *st = fe->demodulator_priv;
+       return &st->dib8096p_tuner_adap;
+}
+EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
+
+int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+       u16 en_cur_state;
+
+       dprintk("sleep dib8096p: %d", onoff);
+
+       en_cur_state = dib8000_read_word(state, 1922);
+
+       /* LNAs and MIX are ON and therefore it is a valid configuration */
+       if (en_cur_state > 0xff)
+               state->tuner_enable = en_cur_state ;
+
+       if (onoff)
+               en_cur_state &= 0x00ff;
+       else {
+               if (state->tuner_enable != 0)
+                       en_cur_state = state->tuner_enable;
+       }
+
+       dib8000_write_word(state, 1922, en_cur_state);
+
+       return 0;
+}
+EXPORT_SYMBOL(dib8096p_tuner_sleep);
+
 static const s32 lut_1000ln_mant[] =
 {
        908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
@@ -1051,6 +1815,26 @@ s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
 }
 EXPORT_SYMBOL(dib8000_get_adc_power);
 
+int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+       int val = 0;
+
+       switch (IQ) {
+       case 1:
+                       val = dib8000_read_word(state, 403);
+                       break;
+       case 0:
+                       val = dib8000_read_word(state, 404);
+                       break;
+       }
+       if (val  & 0x200)
+               val -= 1024;
+
+       return val;
+}
+EXPORT_SYMBOL(dib8090p_get_dc_power);
+
 static void dib8000_update_timf(struct dib8000_state *state)
 {
        u32 timf = state->timf = dib8000_read32(state, 435);
@@ -1060,6 +1844,26 @@ static void dib8000_update_timf(struct dib8000_state *state)
        dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
 }
 
+u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+{
+       struct dib8000_state *state = fe->demodulator_priv;
+
+       switch (op) {
+       case DEMOD_TIMF_SET:
+                       state->timf = timf;
+                       break;
+       case DEMOD_TIMF_UPDATE:
+                       dib8000_update_timf(state);
+                       break;
+       case DEMOD_TIMF_GET:
+                       break;
+       }
+       dib8000_set_bandwidth(state->fe[0], 6000);
+
+       return state->timf;
+}
+EXPORT_SYMBOL(dib8000_ctrl_timf);
+
 static const u16 adc_target_16dB[11] = {
        (1 << 13) - 825 - 117,
        (1 << 13) - 837 - 117,
@@ -1086,6 +1890,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear
        u16 init_prbs = 0xfff;
        u16 ana_gain = 0;
 
+       if (state->revision == 0x8090)
+               dib8000_init_sdram(state);
+
        if (state->ber_monitored_layer != LAYER_ALL)
                dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
        else
@@ -1418,7 +2225,10 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear
        dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
 
        state->differential_constellation = (seg_diff_mask != 0);
-       dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+       if (state->revision != 0x8090)
+               dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+       else
+               dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff);
 
        if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
                if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
@@ -1870,7 +2680,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
        int ret = 0;
-       u16 value, mode = fft_to_mode(state);
+       u16 lock, value, mode = fft_to_mode(state);
 
        // we are already tuned - just resuming from suspend
        if (state == NULL)
@@ -1924,7 +2734,11 @@ static int dib8000_tune(struct dvb_frontend *fe)
        }
 
        // we achieved a coff_cpil_lock - it's time to update the timf
-       if ((dib8000_read_word(state, 568) >> 11) & 0x1)
+       if (state->revision != 0x8090)
+               lock = dib8000_read_word(state, 568);
+       else
+               lock = dib8000_read_word(state, 570);
+       if ((lock >> 11) & 0x1)
                dib8000_update_timf(state);
 
        //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start
@@ -1946,11 +2760,14 @@ static int dib8000_wakeup(struct dvb_frontend *fe)
        u8 index_frontend;
        int ret;
 
-       dib8000_set_power_mode(state, DIB8000M_POWER_ALL);
+       dib8000_set_power_mode(state, DIB8000_POWER_ALL);
        dib8000_set_adc_state(state, DIBX000_ADC_ON);
        if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
                dprintk("could not start Slow ADC");
 
+       if (state->revision != 0x8090)
+               dib8000_sad_calib(state);
+
        for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
                ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
                if (ret < 0)
@@ -1972,8 +2789,9 @@ static int dib8000_sleep(struct dvb_frontend *fe)
                        return ret;
        }
 
-       dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
-       dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY);
+       if (state->revision != 0x8090)
+               dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
+       dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
        return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
 }
 
@@ -1992,7 +2810,7 @@ int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tun
 }
 EXPORT_SYMBOL(dib8000_set_tune_state);
 
-static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib8000_get_frontend(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
        u16 i, val = 0;
@@ -2006,7 +2824,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                if (stat&FE_HAS_SYNC) {
                        dprintk("TMCC lock on the slave%i", index_frontend);
                        /* synchronize the cache with the other frontends */
-                       state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+                       state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
                        for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
                                if (sub_index_frontend != index_frontend) {
                                        state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@@ -2028,7 +2846,10 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
 
        fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
 
-       val = dib8000_read_word(state, 570);
+       if (state->revision == 0x8090)
+               val = dib8000_read_word(state, 572);
+       else
+               val = dib8000_read_word(state, 570);
        fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
        switch ((val & 0x30) >> 4) {
        case 1:
@@ -2135,7 +2956,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        return 0;
 }
 
-static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib8000_set_frontend(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
        u8 nbr_pending, exit_condition, index_frontend;
@@ -2158,9 +2979,14 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
                memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
 
-               dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
+               if (state->revision != 0x8090)
+                       dib8000_set_output_mode(state->fe[index_frontend],
+                                       OUTMODE_HIGH_Z);
+               else
+                       dib8096p_set_output_mode(state->fe[index_frontend],
+                                       OUTMODE_HIGH_Z);
                if (state->fe[index_frontend]->ops.tuner_ops.set_params)
-                       state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend], fep);
+                       state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
 
                dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
        }
@@ -2215,7 +3041,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                         ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
                          ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
                         ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
-               int i = 80000;
+               int i = 100;
                u8 found = 0;
                u8 tune_failed = 0;
 
@@ -2243,6 +3069,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                                        default:
                                                 dprintk("unhandled autosearch result");
                                        case 1:
+                                                tune_failed |= (1 << index_frontend);
                                                 dprintk("autosearch failed for the frontend%i", index_frontend);
                                                 break;
                                        }
@@ -2261,21 +3088,44 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
 
                dprintk("tune success on frontend%i", index_frontend_success);
 
-               dib8000_get_frontend(fe, fep);
+               dib8000_get_frontend(fe);
        }
 
        for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
                ret = dib8000_tune(state->fe[index_frontend]);
 
        /* set output mode and diversity input */
-       dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
-       for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-               dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
-               dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
-       }
+       if (state->revision != 0x8090) {
+               dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
+               for (index_frontend = 1;
+                               (index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+                               (state->fe[index_frontend] != NULL);
+                               index_frontend++) {
+                       dib8000_set_output_mode(state->fe[index_frontend],
+                                       OUTMODE_DIVERSITY);
+                       dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
+               }
 
-       /* turn off the diversity of the last chip */
-       dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
+               /* turn off the diversity of the last chip */
+               dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
+       } else {
+               dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
+               if (state->cfg.enMpegOutput == 0) {
+                       dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
+                       dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+               }
+               for (index_frontend = 1;
+                               (index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+                               (state->fe[index_frontend] != NULL);
+                               index_frontend++) {
+                       dib8096p_set_output_mode(state->fe[index_frontend],
+                                       OUTMODE_DIVERSITY);
+                       dib8096p_set_diversity_in(state->fe[index_frontend-1], 1);
+               }
+
+               /* turn off the diversity of the last chip */
+               dib8096p_set_diversity_in(state->fe[index_frontend-1], 0);
+       }
 
        return ret;
 }
@@ -2284,15 +3134,22 @@ static u16 dib8000_read_lock(struct dvb_frontend *fe)
 {
        struct dib8000_state *state = fe->demodulator_priv;
 
+       if (state->revision == 0x8090)
+               return dib8000_read_word(state, 570);
        return dib8000_read_word(state, 568);
 }
 
 static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 {
        struct dib8000_state *state = fe->demodulator_priv;
-       u16 lock_slave = 0, lock = dib8000_read_word(state, 568);
+       u16 lock_slave = 0, lock;
        u8 index_frontend;
 
+       if (state->revision == 0x8090)
+               lock = dib8000_read_word(state, 570);
+       else
+               lock = dib8000_read_word(state, 568);
+
        for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
                lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
 
@@ -2330,14 +3187,26 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
 {
        struct dib8000_state *state = fe->demodulator_priv;
-       *ber = (dib8000_read_word(state, 560) << 16) | dib8000_read_word(state, 561);   // 13 segments
+
+       /* 13 segments */
+       if (state->revision == 0x8090)
+               *ber = (dib8000_read_word(state, 562) << 16) |
+                       dib8000_read_word(state, 563);
+       else
+               *ber = (dib8000_read_word(state, 560) << 16) |
+                       dib8000_read_word(state, 561);
        return 0;
 }
 
 static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
 {
        struct dib8000_state *state = fe->demodulator_priv;
-       *unc = dib8000_read_word(state, 565);   // packet error on 13 seg
+
+       /* packet error on 13 seg */
+       if (state->revision == 0x8090)
+               *unc = dib8000_read_word(state, 567);
+       else
+               *unc = dib8000_read_word(state, 565);
        return 0;
 }
 
@@ -2370,14 +3239,20 @@ static u32 dib8000_get_snr(struct dvb_frontend *fe)
        u32 n, s, exp;
        u16 val;
 
-       val = dib8000_read_word(state, 542);
+       if (state->revision != 0x8090)
+               val = dib8000_read_word(state, 542);
+       else
+               val = dib8000_read_word(state, 544);
        n = (val >> 6) & 0xff;
        exp = (val & 0x3f);
        if ((exp & 0x20) != 0)
                exp -= 0x40;
        n <<= exp+16;
 
-       val = dib8000_read_word(state, 543);
+       if (state->revision != 0x8090)
+               val = dib8000_read_word(state, 543);
+       else
+               val = dib8000_read_word(state, 545);
        s = (val >> 6) & 0xff;
        exp = (val & 0x3f);
        if ((exp & 0x20) != 0)
@@ -2401,7 +3276,7 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
        for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
                snr_master += dib8000_get_snr(state->fe[index_frontend]);
 
-       if (snr_master != 0) {
+       if ((snr_master >> 16) != 0) {
                snr_master = 10*intlog10(snr_master>>16);
                *snr = snr_master / ((1 << 24) / 10);
        }
@@ -2458,7 +3333,8 @@ struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int sla
 EXPORT_SYMBOL(dib8000_get_slave_frontend);
 
 
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+               u8 default_addr, u8 first_addr, u8 is_dib8096p)
 {
        int k = 0, ret = 0;
        u8 new_addr = 0;
@@ -2488,9 +3364,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
                new_addr = first_addr + (k << 1);
 
                client.addr = new_addr;
-               dib8000_i2c_write16(&client, 1287, 0x0003);     /* sram lead in, rdy */
-               if (dib8000_identify(&client) == 0) {
+               if (!is_dib8096p)
                        dib8000_i2c_write16(&client, 1287, 0x0003);     /* sram lead in, rdy */
+               if (dib8000_identify(&client) == 0) {
+                       /* sram lead in, rdy */
+                       if (!is_dib8096p)
+                               dib8000_i2c_write16(&client, 1287, 0x0003);
                        client.addr = default_addr;
                        if (dib8000_identify(&client) == 0) {
                                dprintk("#%d: not identified", k);
@@ -2549,6 +3428,7 @@ static void dib8000_release(struct dvb_frontend *fe)
                dvb_frontend_detach(st->fe[index_frontend]);
 
        dibx000_exit_i2c_master(&st->i2c_master);
+       i2c_del_adapter(&st->dib8096p_tuner_adap);
        kfree(st->fe[0]);
        kfree(st);
 }
@@ -2581,9 +3461,9 @@ int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 EXPORT_SYMBOL(dib8000_pid_filter);
 
 static const struct dvb_frontend_ops dib8000_ops = {
+       .delsys = { SYS_ISDBT },
        .info = {
                 .name = "DiBcom 8000 ISDB-T",
-                .type = FE_OFDM,
                 .frequency_min = 44250000,
                 .frequency_max = 867250000,
                 .frequency_stepsize = 62500,
@@ -2651,6 +3531,15 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
 
        dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
 
+       /* init 8096p tuner adapter */
+       strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
+                       sizeof(state->dib8096p_tuner_adap.name));
+       state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
+       state->dib8096p_tuner_adap.algo_data = NULL;
+       state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
+       i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
+       i2c_add_adapter(&state->dib8096p_tuner_adap);
+
        dib8000_reset(fe);
 
        dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));     /* ber_rs_len = 3 */
index 617f9eba3a0967787eaa49b7da18f08d61473725..39591bb172c1e0fa4fed5a349e736bba221c3d4a 100644 (file)
@@ -32,6 +32,7 @@ struct dib8000_config {
        u8 div_cfg;
        u8 output_mode;
        u8 refclksel;
+       u8 enMpegOutput:1;
 };
 
 #define DEFAULT_DIB8000_I2C_ADDRESS 18
@@ -40,7 +41,8 @@ struct dib8000_config {
 extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
 extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
 
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
+extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+               u8 default_addr, u8 first_addr, u8 is_dib8096p);
 
 extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
 extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
@@ -50,6 +52,13 @@ extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_st
 extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
 extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
 extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
+extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
+extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
+extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
+extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+               uint8_t op, uint32_t timf);
+extern int dib8000_update_pll(struct dvb_frontend *fe,
+               struct dibx000_bandwidth_config *pll);
 extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
 extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
 extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
@@ -66,7 +75,9 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe
        return NULL;
 }
 
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
+               int no_of_demods, u8 default_addr, u8 first_addr,
+               u8 is_dib8096p)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return -ENODEV;
@@ -109,11 +120,38 @@ static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 }
+static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
 static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return 0;
 }
+static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+               uint8_t op, uint32_t timf)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+static inline int dib8000_update_pll(struct dvb_frontend *fe,
+               struct dibx000_bandwidth_config *pll)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
 static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
index 660f80661ed48f5af1eb21c5e584e9d89f3a592f..863ef3cfab9f908b59c195a77960c7bb779b120c 100644 (file)
@@ -1136,7 +1136,7 @@ static int dib9000_fw_init(struct dib9000_state *state)
        return 0;
 }
 
-static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_frontend_parameters *ch)
+static void dib9000_fw_set_channel_head(struct dib9000_state *state)
 {
        u8 b[9];
        u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
@@ -1157,7 +1157,7 @@ static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_
        dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
 }
 
-static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+static int dib9000_fw_get_channel(struct dvb_frontend *fe)
 {
        struct dib9000_state *state = fe->demodulator_priv;
        struct dibDVBTChannel {
@@ -1309,7 +1309,7 @@ error:
        return ret;
 }
 
-static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
 {
        struct dib9000_state *state = fe->demodulator_priv;
        struct dibDVBTChannel {
@@ -1454,7 +1454,7 @@ static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_fron
        return 0;
 }
 
-static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib9000_fw_tune(struct dvb_frontend *fe)
 {
        struct dib9000_state *state = fe->demodulator_priv;
        int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
@@ -1462,7 +1462,7 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
 
        switch (state->tune_state) {
        case CT_DEMOD_START:
-               dib9000_fw_set_channel_head(state, ch);
+               dib9000_fw_set_channel_head(state);
 
                /* write the channel context - a channel is initialized to 0, so it is OK */
                dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
@@ -1471,7 +1471,7 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
                if (search)
                        dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
                else {
-                       dib9000_fw_set_channel_union(fe, ch);
+                       dib9000_fw_set_channel_union(fe);
                        dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
                }
                state->tune_state = CT_DEMOD_STEP_1;
@@ -1867,7 +1867,7 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron
        return 0;
 }
 
-static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib9000_get_frontend(struct dvb_frontend *fe)
 {
        struct dib9000_state *state = fe->demodulator_priv;
        u8 index_frontend, sub_index_frontend;
@@ -1883,7 +1883,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                        dprintk("TPS lock on the slave%i", index_frontend);
 
                        /* synchronize the cache with the other frontends */
-                       state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+                       state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
                        for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
                             sub_index_frontend++) {
                                if (sub_index_frontend != index_frontend) {
@@ -1911,7 +1911,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        }
 
        /* get the channel from master chip */
-       ret = dib9000_fw_get_channel(fe, fep);
+       ret = dib9000_fw_get_channel(fe);
        if (ret != 0)
                goto return_value;
 
@@ -1958,7 +1958,7 @@ static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_fronte
        return 0;
 }
 
-static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib9000_set_frontend(struct dvb_frontend *fe)
 {
        struct dib9000_state *state = fe->demodulator_priv;
        int sleep_time, sleep_time_slave;
@@ -1983,8 +1983,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        fe->dtv_property_cache.delivery_system = SYS_DVBT;
 
        /* set the master status */
-       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
-           fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+       if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
+           state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
+           state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
+           state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
                /* no channel specified, autosearch the channel */
                state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
        } else
@@ -2008,9 +2010,9 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        exit_condition = 0;     /* 0: tune pending; 1: tune failed; 2:tune success */
        index_frontend_success = 0;
        do {
-               sleep_time = dib9000_fw_tune(state->fe[0], NULL);
+               sleep_time = dib9000_fw_tune(state->fe[0]);
                for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-                       sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+                       sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
                        if (sleep_time == FE_CALLBACK_TIME_NEVER)
                                sleep_time = sleep_time_slave;
                        else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
@@ -2052,7 +2054,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
 
        /* synchronize all the channel cache */
        state->get_frontend_internal = 1;
-       dib9000_get_frontend(state->fe[0], fep);
+       dib9000_get_frontend(state->fe[0]);
        state->get_frontend_internal = 0;
 
        /* retune the other frontends with the found channel */
@@ -2068,7 +2070,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
                sleep_time = FE_CALLBACK_TIME_NEVER;
                for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
                        if (index_frontend != index_frontend_success) {
-                               sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+                               sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
                                if (sleep_time == FE_CALLBACK_TIME_NEVER)
                                        sleep_time = sleep_time_slave;
                                else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
@@ -2495,9 +2497,9 @@ error:
 EXPORT_SYMBOL(dib9000_attach);
 
 static struct dvb_frontend_ops dib9000_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                 .name = "DiBcom 9000",
-                .type = FE_OFDM,
                 .frequency_min = 44250000,
                 .frequency_max = 867250000,
                 .frequency_stepsize = 62500,
index 5e011474be430658b1b13d283bd2f7e11d5c2ca6..5f484881d7b1d07735af0cb4bf7219c441e74ac7 100644 (file)
@@ -146,14 +146,8 @@ enum dibx000_adc_states {
        DIBX000_VBG_DISABLE,
 };
 
-#define BANDWIDTH_TO_KHZ(v) ((v) == BANDWIDTH_8_MHZ  ? 8000 : \
-                               (v) == BANDWIDTH_7_MHZ  ? 7000 : \
-                               (v) == BANDWIDTH_6_MHZ  ? 6000 : 8000)
-
-#define BANDWIDTH_TO_INDEX(v) ( \
-       (v) == 8000 ? BANDWIDTH_8_MHZ : \
-               (v) == 7000 ? BANDWIDTH_7_MHZ : \
-               (v) == 6000 ? BANDWIDTH_6_MHZ : BANDWIDTH_8_MHZ )
+#define BANDWIDTH_TO_KHZ(v)    ((v) / 1000)
+#define BANDWIDTH_TO_HZ(v)     ((v) * 1000)
 
 /* Chip output mode. */
 #define OUTMODE_HIGH_Z              0
@@ -276,4 +270,11 @@ struct dibSubbandSelection {
 #define DEMOD_TIMF_GET    0x01
 #define DEMOD_TIMF_UPDATE 0x02
 
+#define MPEG_ON_DIBTX          1
+#define DIV_ON_DIBTX           2
+#define ADC_ON_DIBTX           3
+#define DEMOUT_ON_HOSTBUS      4
+#define DIBTX_ON_HOSTBUS       5
+#define MPEG_ON_HOSTBUS                6
+
 #endif
index 7113535844f2304f58e24571f538b9a71528cfb9..34398738f9bcc42fce6352db66966a2557f22b64 100644 (file)
@@ -48,8 +48,6 @@ struct drxd_config {
        u8 disable_i2c_gate_ctrl;
 
        u32 IF;
-       int (*pll_set) (void *priv, void *priv_params,
-                       u8 pll_addr, u8 demoda_addr, s32 *off);
         s16(*osc_deviation) (void *priv, s16 dev, int flag);
 };
 
index 88e46f4cdbb26c77a14fbeef942fb6df3682fa4f..7bf39cda83c55ef8305a72e5ca9a571db9d86e8b 100644 (file)
@@ -120,7 +120,7 @@ enum EIFFilter {
 struct drxd_state {
        struct dvb_frontend frontend;
        struct dvb_frontend_ops ops;
-       struct dvb_frontend_parameters param;
+       struct dtv_frontend_properties props;
 
        const struct firmware *fw;
        struct device *dev;
@@ -914,14 +914,13 @@ static int load_firmware(struct drxd_state *state, const char *fw_name)
                return -EIO;
        }
 
-       state->microcode = kmalloc(fw->size, GFP_KERNEL);
+       state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
        if (state->microcode == NULL) {
                release_firmware(fw);
                printk(KERN_ERR "drxd: firmware load failure: no memory\n");
                return -ENOMEM;
        }
 
-       memcpy(state->microcode, fw->data, fw->size);
        state->microcode_length = fw->size;
        release_firmware(fw);
        return 0;
@@ -1622,14 +1621,14 @@ static int CorrectSysClockDeviation(struct drxd_state *state)
                                break;
                }
 
-               switch (state->param.u.ofdm.bandwidth) {
-               case BANDWIDTH_8_MHZ:
+               switch (state->props.bandwidth_hz) {
+               case 8000000:
                        bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
                        break;
-               case BANDWIDTH_6_MHZ:
+               case 6000000:
                        bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
                        break;
                default:
@@ -1804,7 +1803,7 @@ static int StartDiversity(struct drxd_state *state)
                        status = WriteTable(state, state->m_StartDiversityEnd);
                        if (status < 0)
                                break;
-                       if (state->param.u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
+                       if (state->props.bandwidth_hz == 8000000) {
                                status = WriteTable(state, state->m_DiversityDelay8MHZ);
                                if (status < 0)
                                        break;
@@ -1906,7 +1905,7 @@ static int SetCfgNoiseCalibration(struct drxd_state *state,
 
 static int DRX_Start(struct drxd_state *state, s32 off)
 {
-       struct dvb_ofdm_parameters *p = &state->param.u.ofdm;
+       struct dtv_frontend_properties *p = &state->props;
        int status;
 
        u16 transmissionParams = 0;
@@ -1971,7 +1970,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
                if (status < 0)
                        break;
 
-               mirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+               mirrorFreqSpect = (state->props.inversion == INVERSION_ON);
 
                switch (p->transmission_mode) {
                default:        /* Not set, detect it automatically */
@@ -2021,7 +2020,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
                        break;
                }
 
-               switch (p->hierarchy_information) {
+               switch (p->hierarchy) {
                case HIERARCHY_1:
                        transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1;
                        if (state->type_A) {
@@ -2147,7 +2146,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
                if (status < 0)
                        break;
 
-               switch (p->constellation) {
+               switch (p->modulation) {
                default:
                        operationMode |= SC_RA_RAM_OP_AUTO_CONST__M;
                        /* fall through , try first guess
@@ -2331,9 +2330,11 @@ static int DRX_Start(struct drxd_state *state, s32 off)
                   by SC for fix for some 8K,1/8 guard but is restored by
                   InitEC and ResetEC
                   functions */
-               switch (p->bandwidth) {
-               case BANDWIDTH_AUTO:
-               case BANDWIDTH_8_MHZ:
+               switch (p->bandwidth_hz) {
+               case 0:
+                       p->bandwidth_hz = 8000000;
+                       /* fall through */
+               case 8000000:
                        /* (64/7)*(8/8)*1000000 */
                        bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
 
@@ -2341,14 +2342,14 @@ static int DRX_Start(struct drxd_state *state, s32 off)
                        status = Write16(state,
                                         FE_AG_REG_IND_DEL__A, 50, 0x0000);
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        /* (64/7)*(7/8)*1000000 */
                        bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
                        bandwidthParam = 0x4807;        /*binary:0100 1000 0000 0111 */
                        status = Write16(state,
                                         FE_AG_REG_IND_DEL__A, 59, 0x0000);
                        break;
-               case BANDWIDTH_6_MHZ:
+               case 6000000:
                        /* (64/7)*(6/8)*1000000 */
                        bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
                        bandwidthParam = 0x0F07;        /*binary: 0000 1111 0000 0111 */
@@ -2887,41 +2888,26 @@ static int drxd_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int drxd_get_frontend(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *param)
-{
-       return 0;
-}
-
 static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        return drxd_config_i2c(fe, enable);
 }
 
-static int drxd_set_frontend(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *param)
+static int drxd_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct drxd_state *state = fe->demodulator_priv;
        s32 off = 0;
 
-       state->param = *param;
+       state->props = *p;
        DRX_Stop(state);
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       /* FIXME: move PLL drivers */
-       if (state->config.pll_set &&
-           state->config.pll_set(state->priv, param,
-                                 state->config.pll_address,
-                                 state->config.demoda_address, &off) < 0) {
-               printk(KERN_ERR "Error in pll_set\n");
-               return -1;
-       }
-
        msleep(200);
 
        return DRX_Start(state, off);
@@ -2935,10 +2921,9 @@ static void drxd_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops drxd_ops = {
-
+       .delsys = { SYS_DVBT},
        .info = {
                 .name = "Micronas DRXD DVB-T",
-                .type = FE_OFDM,
                 .frequency_min = 47125000,
                 .frequency_max = 855250000,
                 .frequency_stepsize = 166667,
@@ -2958,7 +2943,6 @@ static struct dvb_frontend_ops drxd_ops = {
        .i2c_gate_ctrl = drxd_i2c_gate_ctrl,
 
        .set_frontend = drxd_set_frontend,
-       .get_frontend = drxd_get_frontend,
        .get_tune_settings = drxd_get_tune_settings,
 
        .read_status = drxd_read_status,
index 58baf419560cedb55f11ca5b788cbcd9eff77069..020981844a86940c8e2cbe0f5ca0d45cff989048 100644 (file)
@@ -8,6 +8,8 @@
  * struct drxk_config - Configure the initial parameters for DRX-K
  *
  * adr:                        I2C Address of the DRX-K
+ * parallel_ts:                true means that the device uses parallel TS,
+ *                     Serial otherwise.
  * single_master:      Device is on the single master mode
  * no_i2c_bridge:      Don't switch the I2C bridge to talk with tuner
  * antenna_gpio:       GPIO bit used to control the antenna
@@ -22,22 +24,23 @@ struct drxk_config {
        u8      adr;
        bool    single_master;
        bool    no_i2c_bridge;
+       bool    parallel_ts;
 
        bool    antenna_dvbt;
        u16     antenna_gpio;
 
+       int    chunk_size;
+
        const char *microcode_name;
 };
 
 #if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
         && defined(MODULE))
 extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
-                                       struct i2c_adapter *i2c,
-                                       struct dvb_frontend **fe_t);
+                                       struct i2c_adapter *i2c);
 #else
 static inline struct dvb_frontend *drxk_attach(const struct drxk_config *config,
-                                       struct i2c_adapter *i2c,
-                                       struct dvb_frontend **fe_t)
+                                       struct i2c_adapter *i2c)
 {
         printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
         return NULL;
index f6431ef827dc1f86e6b4748ae08c5edb141919ff..6980ed7b8786b6048b5e4271db0f7758bb277204 100644 (file)
@@ -368,10 +368,10 @@ static int i2c_read(struct i2c_adapter *adap,
        }
        if (debug > 2) {
                int i;
-               dprintk(2, ": read from ");
+               dprintk(2, ": read from");
                for (i = 0; i < len; i++)
                        printk(KERN_CONT " %02x", msg[i]);
-               printk(KERN_CONT "Value = ");
+               printk(KERN_CONT ", value = ");
                for (i = 0; i < alen; i++)
                        printk(KERN_CONT " %02x", answ[i]);
                printk(KERN_CONT "\n");
@@ -660,7 +660,6 @@ static int init_state(struct drxk_state *state)
        /* io_pad_cfg_mode output mode is drive always */
        /* io_pad_cfg_drive is set to power 2 (23 mA) */
        u32 ulGPIOCfg = 0x0113;
-       u32 ulSerialMode = 1;
        u32 ulInvertTSClock = 0;
        u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
        u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH;
@@ -681,7 +680,8 @@ static int init_state(struct drxk_state *state)
        state->m_hasOOB = false;
        state->m_hasAudio = false;
 
-       state->m_ChunkSize = 124;
+       if (!state->m_ChunkSize)
+               state->m_ChunkSize = 124;
 
        state->m_oscClockFreq = 0;
        state->m_smartAntInverted = false;
@@ -810,8 +810,6 @@ static int init_state(struct drxk_state *state)
        /* MPEG output configuration */
        state->m_enableMPEGOutput = true;       /* If TRUE; enable MPEG ouput */
        state->m_insertRSByte = false;  /* If TRUE; insert RS byte */
-       state->m_enableParallel = true; /* If TRUE;
-                                          parallel out otherwise serial */
        state->m_invertDATA = false;    /* If TRUE; invert DATA signals */
        state->m_invertERR = false;     /* If TRUE; invert ERR signal */
        state->m_invertSTR = false;     /* If TRUE; invert STR signals */
@@ -856,8 +854,6 @@ static int init_state(struct drxk_state *state)
        state->m_bPowerDown = false;
        state->m_currentPowerMode = DRX_POWER_DOWN;
 
-       state->m_enableParallel = (ulSerialMode == 0);
-
        state->m_rfmirror = (ulRfMirror == 0);
        state->m_IfAgcPol = false;
        return 0;
@@ -946,6 +942,9 @@ static int GetDeviceCapabilities(struct drxk_state *state)
        status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo);
        if (status < 0)
                goto error;
+
+printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo);
+
        /* driver 0.9.0 */
        switch ((sioTopJtagidLo >> 29) & 0xF) {
        case 0:
@@ -963,7 +962,8 @@ static int GetDeviceCapabilities(struct drxk_state *state)
        default:
                state->m_deviceSpin = DRXK_SPIN_UNKNOWN;
                status = -EINVAL;
-               printk(KERN_ERR "drxk: Spin unknown\n");
+               printk(KERN_ERR "drxk: Spin %d unknown\n",
+                      (sioTopJtagidLo >> 29) & 0xF);
                goto error2;
        }
        switch ((sioTopJtagidLo >> 12) & 0xFF) {
@@ -1190,7 +1190,9 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
        u16 sioPdrMclkCfg = 0;
        u16 sioPdrMdxCfg = 0;
 
-       dprintk(1, "\n");
+       dprintk(1, ": mpeg %s, %s mode\n",
+               mpegEnable ? "enable" : "disable",
+               state->m_enableParallel ? "parallel" : "serial");
 
        /* stop lock indicator process */
        status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
@@ -1846,6 +1848,7 @@ static int SetOperationMode(struct drxk_state *state,
                */
        switch (oMode) {
        case OM_DVBT:
+               dprintk(1, ": DVB-T\n");
                state->m_OperationMode = oMode;
                status = SetDVBTStandard(state, oMode);
                if (status < 0)
@@ -1853,6 +1856,8 @@ static int SetOperationMode(struct drxk_state *state,
                break;
        case OM_QAM_ITU_A:      /* fallthrough */
        case OM_QAM_ITU_C:
+               dprintk(1, ": DVB-C Annex %c\n",
+                       (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C');
                state->m_OperationMode = oMode;
                status = SetQAMStandard(state, oMode);
                if (status < 0)
@@ -1881,7 +1886,7 @@ static int Start(struct drxk_state *state, s32 offsetFreq,
                state->m_DrxkState != DRXK_DTV_STARTED)
                goto error;
 
-       state->m_bMirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+       state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON);
 
        if (IntermediateFrequency < 0) {
                state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect;
@@ -2503,7 +2508,7 @@ static int GetQAMSignalToNoise(struct drxk_state *state,
        u16 qamSlErrPower = 0;  /* accum. error between
                                        raw and sliced symbols */
        u32 qamSlSigPower = 0;  /* used for MER, depends of
-                                       QAM constellation */
+                                       QAM modulation */
        u32 qamSlMer = 0;       /* QAM MER */
 
        dprintk(1, "\n");
@@ -2517,7 +2522,7 @@ static int GetQAMSignalToNoise(struct drxk_state *state,
                return -EINVAL;
        }
 
-       switch (state->param.u.qam.modulation) {
+       switch (state->props.modulation) {
        case QAM_16:
                qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
                break;
@@ -2748,7 +2753,7 @@ static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality)
                if (status < 0)
                        break;
 
-               switch (state->param.u.qam.modulation) {
+               switch (state->props.modulation) {
                case QAM_16:
                        SignalToNoiseRel = SignalToNoise - 200;
                        break;
@@ -3813,7 +3818,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
        /*== Write channel settings to device =====================================*/
 
        /* mode */
-       switch (state->param.u.ofdm.transmission_mode) {
+       switch (state->props.transmission_mode) {
        case TRANSMISSION_MODE_AUTO:
        default:
                operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
@@ -3827,7 +3832,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
        }
 
        /* guard */
-       switch (state->param.u.ofdm.guard_interval) {
+       switch (state->props.guard_interval) {
        default:
        case GUARD_INTERVAL_AUTO:
                operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
@@ -3847,7 +3852,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
        }
 
        /* hierarchy */
-       switch (state->param.u.ofdm.hierarchy_information) {
+       switch (state->props.hierarchy) {
        case HIERARCHY_AUTO:
        case HIERARCHY_NONE:
        default:
@@ -3867,8 +3872,8 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
        }
 
 
-       /* constellation */
-       switch (state->param.u.ofdm.constellation) {
+       /* modulation */
+       switch (state->props.modulation) {
        case QAM_AUTO:
        default:
                operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
@@ -3911,7 +3916,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
 #endif
 
        /* coderate */
-       switch (state->param.u.ofdm.code_rate_HP) {
+       switch (state->props.code_rate_HP) {
        case FEC_AUTO:
        default:
                operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
@@ -3940,9 +3945,11 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
        /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
                by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
                functions */
-       switch (state->param.u.ofdm.bandwidth) {
-       case BANDWIDTH_AUTO:
-       case BANDWIDTH_8_MHZ:
+       switch (state->props.bandwidth_hz) {
+       case 0:
+               state->props.bandwidth_hz = 8000000;
+               /* fall though */
+       case 8000000:
                bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
                status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
                if (status < 0)
@@ -3961,7 +3968,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
                if (status < 0)
                        goto error;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
                status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
                if (status < 0)
@@ -3980,7 +3987,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
                if (status < 0)
                        goto error;
                break;
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
                status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
                if (status < 0)
@@ -4187,7 +4194,7 @@ error:
 /**
 * \brief Setup of the QAM Measurement intervals for signal quality
 * \param demod instance of demod.
-* \param constellation current constellation.
+* \param modulation current modulation.
 * \return DRXStatus_t.
 *
 *  NOTE:
@@ -4196,7 +4203,7 @@ error:
 *
 */
 static int SetQAMMeasurement(struct drxk_state *state,
-                            enum EDrxkConstellation constellation,
+                            enum EDrxkConstellation modulation,
                             u32 symbolRate)
 {
        u32 fecBitsDesired = 0; /* BER accounting period */
@@ -4210,11 +4217,11 @@ static int SetQAMMeasurement(struct drxk_state *state,
        fecRsPrescale = 1;
        /* fecBitsDesired = symbolRate [kHz] *
                FrameLenght [ms] *
-               (constellation + 1) *
+               (modulation + 1) *
                SyncLoss (== 1) *
                ViterbiLoss (==1)
                */
-       switch (constellation) {
+       switch (modulation) {
        case DRX_CONSTELLATION_QAM16:
                fecBitsDesired = 4 * symbolRate;
                break;
@@ -5281,12 +5288,12 @@ static int QAMSetSymbolrate(struct drxk_state *state)
        /* Select & calculate correct IQM rate */
        adcFrequency = (state->m_sysClockFreq * 1000) / 3;
        ratesel = 0;
-       /* printk(KERN_DEBUG "drxk: SR %d\n", state->param.u.qam.symbol_rate); */
-       if (state->param.u.qam.symbol_rate <= 1188750)
+       /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */
+       if (state->props.symbol_rate <= 1188750)
                ratesel = 3;
-       else if (state->param.u.qam.symbol_rate <= 2377500)
+       else if (state->props.symbol_rate <= 2377500)
                ratesel = 2;
-       else if (state->param.u.qam.symbol_rate <= 4755000)
+       else if (state->props.symbol_rate <= 4755000)
                ratesel = 1;
        status = write16(state, IQM_FD_RATESEL__A, ratesel);
        if (status < 0)
@@ -5295,7 +5302,7 @@ static int QAMSetSymbolrate(struct drxk_state *state)
        /*
                IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
                */
-       symbFreq = state->param.u.qam.symbol_rate * (1 << ratesel);
+       symbFreq = state->props.symbol_rate * (1 << ratesel);
        if (symbFreq == 0) {
                /* Divide by zero */
                status = -EINVAL;
@@ -5311,7 +5318,7 @@ static int QAMSetSymbolrate(struct drxk_state *state)
        /*
                LcSymbFreq = round (.125 *  symbolrate / adcFreq * (1<<15))
                */
-       symbFreq = state->param.u.qam.symbol_rate;
+       symbFreq = state->props.symbol_rate;
        if (adcFrequency == 0) {
                /* Divide by zero */
                status = -EINVAL;
@@ -5412,7 +5419,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
                goto error;
 
        /* Set params */
-       switch (state->param.u.qam.modulation) {
+       switch (state->props.modulation) {
        case QAM_256:
                state->m_Constellation = DRX_CONSTELLATION_QAM256;
                break;
@@ -5435,7 +5442,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
        }
        if (status < 0)
                goto error;
-       setParamParameters[0] = state->m_Constellation; /* constellation     */
+       setParamParameters[0] = state->m_Constellation; /* modulation     */
        setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
        if (state->m_OperationMode == OM_QAM_ITU_C)
                setParamParameters[2] = QAM_TOP_ANNEX_C;
@@ -5457,7 +5464,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
                if (status < 0)
                        goto error;
 
-               setParamParameters[0] = state->m_Constellation; /* constellation     */
+               setParamParameters[0] = state->m_Constellation; /* modulation     */
                setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
                status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
        }
@@ -5466,7 +5473,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
 
        /*
         * STEP 3: enable the system in a mode where the ADC provides valid
-        * signal setup constellation independent registers
+        * signal setup modulation independent registers
         */
 #if 0
        status = SetFrequency(channel, tunerFreqOffset));
@@ -5478,7 +5485,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
                goto error;
 
        /* Setup BER measurement */
-       status = SetQAMMeasurement(state, state->m_Constellation, state->param.u. qam.symbol_rate);
+       status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate);
        if (status < 0)
                goto error;
 
@@ -5560,8 +5567,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
        if (status < 0)
                goto error;
 
-       /* STEP 4: constellation specific setup */
-       switch (state->param.u.qam.modulation) {
+       /* STEP 4: modulation specific setup */
+       switch (state->props.modulation) {
        case QAM_16:
                status = SetQAM16(state);
                break;
@@ -5591,7 +5598,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
                goto error;
 
        /* Re-configure MPEG output, requires knowledge of channel bitrate */
-       /* extAttr->currentChannel.constellation = channel->constellation; */
+       /* extAttr->currentChannel.modulation = channel->modulation; */
        /* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
        status = MPEGTSDtoSetup(state, state->m_OperationMode);
        if (status < 0)
@@ -6167,7 +6174,7 @@ error:
        return status;
 }
 
-static void drxk_c_release(struct dvb_frontend *fe)
+static void drxk_release(struct dvb_frontend *fe)
 {
        struct drxk_state *state = fe->demodulator_priv;
 
@@ -6175,24 +6182,12 @@ static void drxk_c_release(struct dvb_frontend *fe)
        kfree(state);
 }
 
-static int drxk_c_init(struct dvb_frontend *fe)
-{
-       struct drxk_state *state = fe->demodulator_priv;
-
-       dprintk(1, "\n");
-       if (mutex_trylock(&state->ctlock) == 0)
-               return -EBUSY;
-       SetOperationMode(state, OM_QAM_ITU_A);
-       return 0;
-}
-
-static int drxk_c_sleep(struct dvb_frontend *fe)
+static int drxk_sleep(struct dvb_frontend *fe)
 {
        struct drxk_state *state = fe->demodulator_priv;
 
        dprintk(1, "\n");
        ShutDown(state);
-       mutex_unlock(&state->ctlock);
        return 0;
 }
 
@@ -6204,9 +6199,10 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
        return ConfigureI2CBridge(state, enable ? true : false);
 }
 
-static int drxk_set_parameters(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *p)
+static int drxk_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       u32 delsys  = p->delivery_system, old_delsys;
        struct drxk_state *state = fe->demodulator_priv;
        u32 IF;
 
@@ -6218,14 +6214,39 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
-       state->param = *p;
+
+       old_delsys = state->props.delivery_system;
+       state->props = *p;
+
+       if (old_delsys != delsys) {
+               ShutDown(state);
+               switch (delsys) {
+               case SYS_DVBC_ANNEX_A:
+               case SYS_DVBC_ANNEX_C:
+                       if (!state->m_hasDVBC)
+                               return -EINVAL;
+                       state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false;
+                       if (state->m_itut_annex_c)
+                               SetOperationMode(state, OM_QAM_ITU_C);
+                       else
+                               SetOperationMode(state, OM_QAM_ITU_A);
+                       break;
+               case SYS_DVBT:
+                       if (!state->m_hasDVBT)
+                               return -EINVAL;
+                       SetOperationMode(state, OM_DVBT);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
        fe->ops.tuner_ops.get_if_frequency(fe, &IF);
        Start(state, 0, IF);
 
@@ -6234,13 +6255,6 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
        return 0;
 }
 
-static int drxk_c_get_frontend(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *p)
-{
-       dprintk(1, "\n");
-       return 0;
-}
-
 static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct drxk_state *state = fe->demodulator_priv;
@@ -6300,102 +6314,54 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
        return 0;
 }
 
-static int drxk_c_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
+static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
                                    *sets)
 {
-       dprintk(1, "\n");
-       sets->min_delay_ms = 3000;
-       sets->max_drift = 0;
-       sets->step_size = 0;
-       return 0;
-}
-
-static void drxk_t_release(struct dvb_frontend *fe)
-{
-       /*
-        * There's nothing to release here, as the state struct
-        * is already freed by drxk_c_release.
-        */
-}
-
-static int drxk_t_init(struct dvb_frontend *fe)
-{
-       struct drxk_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
        dprintk(1, "\n");
-       if (mutex_trylock(&state->ctlock) == 0)
-               return -EBUSY;
-       SetOperationMode(state, OM_DVBT);
-       return 0;
-}
-
-static int drxk_t_sleep(struct dvb_frontend *fe)
-{
-       struct drxk_state *state = fe->demodulator_priv;
-
-       dprintk(1, "\n");
-       mutex_unlock(&state->ctlock);
-       return 0;
-}
-
-static int drxk_t_get_frontend(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *p)
-{
-       dprintk(1, "\n");
-
-       return 0;
+       switch (p->delivery_system) {
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               sets->min_delay_ms = 3000;
+               sets->max_drift = 0;
+               sets->step_size = 0;
+               return 0;
+       default:
+               /*
+                * For DVB-T, let it use the default DVB core way, that is:
+                *      fepriv->step_size = fe->ops.info.frequency_stepsize * 2
+                */
+               return -EINVAL;
+       }
 }
 
-static struct dvb_frontend_ops drxk_c_ops = {
+static struct dvb_frontend_ops drxk_ops = {
+       /* .delsys will be filled dynamically */
        .info = {
-                .name = "DRXK DVB-C",
-                .type = FE_QAM,
-                .frequency_stepsize = 62500,
-                .frequency_min = 47000000,
-                .frequency_max = 862000000,
-                .symbol_rate_min = 870000,
-                .symbol_rate_max = 11700000,
-                .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-                FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
-       .release = drxk_c_release,
-       .init = drxk_c_init,
-       .sleep = drxk_c_sleep,
+               .name = "DRXK",
+               .frequency_min = 47000000,
+               .frequency_max = 865000000,
+                /* For DVB-C */
+               .symbol_rate_min = 870000,
+               .symbol_rate_max = 11700000,
+               /* For DVB-T */
+               .frequency_stepsize = 166667,
+
+               .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+                       FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
+                       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_MUTE_TS |
+                       FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
+                       FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
+       },
+
+       .release = drxk_release,
+       .sleep = drxk_sleep,
        .i2c_gate_ctrl = drxk_gate_ctrl,
 
        .set_frontend = drxk_set_parameters,
-       .get_frontend = drxk_c_get_frontend,
-       .get_tune_settings = drxk_c_get_tune_settings,
-
-       .read_status = drxk_read_status,
-       .read_ber = drxk_read_ber,
-       .read_signal_strength = drxk_read_signal_strength,
-       .read_snr = drxk_read_snr,
-       .read_ucblocks = drxk_read_ucblocks,
-};
-
-static struct dvb_frontend_ops drxk_t_ops = {
-       .info = {
-                .name = "DRXK DVB-T",
-                .type = FE_OFDM,
-                .frequency_min = 47125000,
-                .frequency_max = 865000000,
-                .frequency_stepsize = 166667,
-                .frequency_tolerance = 0,
-                .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_QAM_16 | FE_CAN_QAM_64 |
-                FE_CAN_QAM_AUTO |
-                FE_CAN_TRANSMISSION_MODE_AUTO |
-                FE_CAN_GUARD_INTERVAL_AUTO |
-                FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
-       .release = drxk_t_release,
-       .init = drxk_t_init,
-       .sleep = drxk_t_sleep,
-       .i2c_gate_ctrl = drxk_gate_ctrl,
-
-       .set_frontend = drxk_set_parameters,
-       .get_frontend = drxk_t_get_frontend,
+       .get_tune_settings = drxk_get_tune_settings,
 
        .read_status = drxk_read_status,
        .read_ber = drxk_read_ber,
@@ -6405,9 +6371,10 @@ static struct dvb_frontend_ops drxk_t_ops = {
 };
 
 struct dvb_frontend *drxk_attach(const struct drxk_config *config,
-                                struct i2c_adapter *i2c,
-                                struct dvb_frontend **fe_t)
+                                struct i2c_adapter *i2c)
 {
+       int n;
+
        struct drxk_state *state = NULL;
        u8 adr = config->adr;
 
@@ -6423,6 +6390,12 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
        state->no_i2c_bridge = config->no_i2c_bridge;
        state->antenna_gpio = config->antenna_gpio;
        state->antenna_dvbt = config->antenna_dvbt;
+       state->m_ChunkSize = config->chunk_size;
+
+       if (config->parallel_ts)
+               state->m_enableParallel = true;
+       else
+               state->m_enableParallel = false;
 
        /* NOTE: as more UIO bits will be used, add them to the mask */
        state->UIO_mask = config->antenna_gpio;
@@ -6434,21 +6407,30 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
                state->m_GPIO &= ~state->antenna_gpio;
 
        mutex_init(&state->mutex);
-       mutex_init(&state->ctlock);
 
-       memcpy(&state->c_frontend.ops, &drxk_c_ops,
-              sizeof(struct dvb_frontend_ops));
-       memcpy(&state->t_frontend.ops, &drxk_t_ops,
-              sizeof(struct dvb_frontend_ops));
-       state->c_frontend.demodulator_priv = state;
-       state->t_frontend.demodulator_priv = state;
+       memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
+       state->frontend.demodulator_priv = state;
 
        init_state(state);
        if (init_drxk(state) < 0)
                goto error;
-       *fe_t = &state->t_frontend;
 
-       return &state->c_frontend;
+       /* Initialize the supported delivery systems */
+       n = 0;
+       if (state->m_hasDVBC) {
+               state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
+               state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
+               strlcat(state->frontend.ops.info.name, " DVB-C",
+                       sizeof(state->frontend.ops.info.name));
+       }
+       if (state->m_hasDVBT) {
+               state->frontend.ops.delsys[n++] = SYS_DVBT;
+               strlcat(state->frontend.ops.info.name, " DVB-T",
+                       sizeof(state->frontend.ops.info.name));
+       }
+
+       printk(KERN_INFO "drxk: frontend initialized.\n");
+       return &state->frontend;
 
 error:
        printk(KERN_ERR "drxk: not found\n");
index a05c32eecdcc7de893a297c6faf53b54324a040c..3a58b73eb9b97f158e16f28b43c41a47a704bddd 100644 (file)
@@ -195,9 +195,8 @@ struct DRXKOfdmScCmd_t {
 };
 
 struct drxk_state {
-       struct dvb_frontend c_frontend;
-       struct dvb_frontend t_frontend;
-       struct dvb_frontend_parameters param;
+       struct dvb_frontend frontend;
+       struct dtv_frontend_properties props;
        struct device *dev;
 
        struct i2c_adapter *i2c;
@@ -205,7 +204,6 @@ struct drxk_state {
        void  *priv;
 
        struct mutex mutex;
-       struct mutex ctlock;
 
        u32    m_Instance;           /**< Channel 1,2,3 or 4 */
 
@@ -263,6 +261,8 @@ struct drxk_state {
        u8     m_TSDataStrength;
        u8     m_TSClockkStrength;
 
+       bool   m_itut_annex_c;      /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */
+
        enum DRXMPEGStrWidth_t  m_widthSTR;    /**< MPEG start width */
        u32    m_mpegTsStaticBitrate;          /**< Maximum bitrate in b/s in case
                                                    static clockrate is selected */
index 90bf573308b0eb51c7507d99206e01ac9af4747a..938777065de6d1d14effed1ab4f9a01b3f7dc8c7 100644 (file)
@@ -934,20 +934,6 @@ error2:
 }
 EXPORT_SYMBOL(ds3000_attach);
 
-static int ds3000_set_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
-static int ds3000_get_property(struct dvb_frontend *fe,
-       struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
 static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
                                        s32 carrier_offset_khz)
 {
@@ -967,8 +953,7 @@ static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
        return 0;
 }
 
-static int ds3000_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int ds3000_set_frontend(struct dvb_frontend *fe)
 {
        struct ds3000_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -994,15 +979,15 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
        div4 = 0;
 
        /* calculate and set freq divider */
-       if (p->frequency < 1146000) {
+       if (c->frequency < 1146000) {
                ds3000_tuner_writereg(state, 0x10, 0x11);
                div4 = 1;
-               ndiv = ((p->frequency * (6 + 8) * 4) +
+               ndiv = ((c->frequency * (6 + 8) * 4) +
                                (DS3000_XTAL_FREQ / 2)) /
                                DS3000_XTAL_FREQ - 1024;
        } else {
                ds3000_tuner_writereg(state, 0x10, 0x01);
-               ndiv = ((p->frequency * (6 + 8) * 2) +
+               ndiv = ((c->frequency * (6 + 8) * 2) +
                                (DS3000_XTAL_FREQ / 2)) /
                                DS3000_XTAL_FREQ - 1024;
        }
@@ -1101,7 +1086,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
        msleep(60);
 
        offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ
-               / (6 + 8) / (div4 + 1) / 2 - p->frequency;
+               / (6 + 8) / (div4 + 1) / 2 - c->frequency;
 
        /* ds3000 global reset */
        ds3000_writereg(state, 0x07, 0x80);
@@ -1220,13 +1205,13 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
 }
 
 static int ds3000_tune(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *p,
+                       bool re_tune,
                        unsigned int mode_flags,
                        unsigned int *delay,
                        fe_status_t *status)
 {
-       if (p) {
-               int ret = ds3000_set_frontend(fe, p);
+       if (re_tune) {
+               int ret = ds3000_set_frontend(fe);
                if (ret)
                        return ret;
        }
@@ -1279,10 +1264,9 @@ static int ds3000_sleep(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops ds3000_ops = {
-
+       .delsys = { SYS_DVBS, SYS_DVBS2},
        .info = {
                .name = "Montage Technology DS3000/TS2020",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1011, /* kHz for QPSK frontends */
@@ -1312,8 +1296,6 @@ static struct dvb_frontend_ops ds3000_ops = {
        .diseqc_send_burst = ds3000_diseqc_send_burst,
        .get_frontend_algo = ds3000_get_algo,
 
-       .set_property = ds3000_set_property,
-       .get_property = ds3000_get_property,
        .set_frontend = ds3000_set_frontend,
        .tune = ds3000_tune,
 };
index 62a65efdf8d6133817beb5b8dbbaf0f2e47d12e2..1ab34838221c0b14d09bdfec5bb67bbce382bd1c 100644 (file)
@@ -61,8 +61,7 @@ struct dvb_pll_desc {
        u32  min;
        u32  max;
        u32  iffreq;
-       void (*set)(struct dvb_frontend *fe, u8 *buf,
-                   const struct dvb_frontend_parameters *params);
+       void (*set)(struct dvb_frontend *fe, u8 *buf);
        u8   *initdata;
        u8   *initdata2;
        u8   *sleepdata;
@@ -93,10 +92,10 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        },
 };
 
-static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
-                              const struct dvb_frontend_parameters *params)
+static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
 {
-       if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth)
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       if (bw == 7000000)
                buf[3] |= 0x10;
 }
 
@@ -186,10 +185,10 @@ static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
 /* Philips TDA6650/TDA6651
  * used in Panasonic ENV77H11D5
  */
-static void tda665x_bw(struct dvb_frontend *fe, u8 *buf,
-                      const struct dvb_frontend_parameters *params)
+static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
 {
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       if (bw == 8000000)
                buf[3] |= 0x08;
 }
 
@@ -220,10 +219,10 @@ static struct dvb_pll_desc dvb_pll_tda665x = {
 /* Infineon TUA6034
  * used in LG TDTP E102P
  */
-static void tua6034_bw(struct dvb_frontend *fe, u8 *buf,
-                      const struct dvb_frontend_parameters *params)
+static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
 {
-       if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth)
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       if (bw == 7000000)
                buf[3] |= 0x08;
 }
 
@@ -244,10 +243,10 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
 /* ALPS TDED4
  * used in Nebula-Cards and USB boxes
  */
-static void tded4_bw(struct dvb_frontend *fe, u8 *buf,
-                    const struct dvb_frontend_parameters *params)
+static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
 {
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       if (bw == 8000000)
                buf[3] |= 0x04;
 }
 
@@ -319,11 +318,11 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
        },
 };
 
-static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
-                     const struct dvb_frontend_parameters *params)
+static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_pll_priv *priv = fe->tuner_priv;
-       u32 b_w  = (params->u.qpsk.symbol_rate * 27) / 32000;
+       u32 b_w  = (c->symbol_rate * 27) / 32000;
        struct i2c_msg msg = {
                .addr = priv->pll_i2c_address,
                .flags = 0,
@@ -392,8 +391,7 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
        }
 };
 
-static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
-                      const struct dvb_frontend_parameters *params)
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
 {
        struct dvb_pll_priv *priv = fe->tuner_priv;
        struct i2c_msg msg = {
@@ -537,30 +535,29 @@ static struct dvb_pll_desc *pll_list[] = {
 /* code                                                        */
 
 static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
-                            const struct dvb_frontend_parameters *params)
+                            const u32 frequency)
 {
        struct dvb_pll_priv *priv = fe->tuner_priv;
        struct dvb_pll_desc *desc = priv->pll_desc;
        u32 div;
        int i;
 
-       if (params->frequency != 0 && (params->frequency < desc->min ||
-                                      params->frequency > desc->max))
+       if (frequency && (frequency < desc->min || frequency > desc->max))
                return -EINVAL;
 
        for (i = 0; i < desc->count; i++) {
-               if (params->frequency > desc->entries[i].limit)
+               if (frequency > desc->entries[i].limit)
                        continue;
                break;
        }
 
        if (debug)
                printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
-                      params->frequency, i, desc->count);
+                      frequency, i, desc->count);
        if (i == desc->count)
                return -EINVAL;
 
-       div = (params->frequency + desc->iffreq +
+       div = (frequency + desc->iffreq +
               desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
        buf[0] = div >> 8;
        buf[1] = div & 0xff;
@@ -568,7 +565,7 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
        buf[3] = desc->entries[i].cb;
 
        if (desc->set)
-               desc->set(fe, buf, params);
+               desc->set(fe, buf);
 
        if (debug)
                printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
@@ -611,9 +608,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
        return -EINVAL;
 }
 
-static int dvb_pll_set_params(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *params)
+static int dvb_pll_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_pll_priv *priv = fe->tuner_priv;
        u8 buf[4];
        struct i2c_msg msg =
@@ -625,7 +622,8 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
        if (priv->i2c == NULL)
                return -EINVAL;
 
-       if ((result = dvb_pll_configure(fe, buf, params)) < 0)
+       result = dvb_pll_configure(fe, buf, c->frequency);
+       if (result < 0)
                return result;
        else
                frequency = result;
@@ -637,15 +635,15 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
        }
 
        priv->frequency = frequency;
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+       priv->bandwidth = c->bandwidth_hz;
 
        return 0;
 }
 
 static int dvb_pll_calc_regs(struct dvb_frontend *fe,
-                            struct dvb_frontend_parameters *params,
                             u8 *buf, int buf_len)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_pll_priv *priv = fe->tuner_priv;
        int result;
        u32 frequency = 0;
@@ -653,7 +651,8 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
        if (buf_len < 5)
                return -EINVAL;
 
-       if ((result = dvb_pll_configure(fe, buf+1, params)) < 0)
+       result = dvb_pll_configure(fe, buf + 1, c->frequency);
+       if (result < 0)
                return result;
        else
                frequency = result;
@@ -661,7 +660,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
        buf[0] = priv->pll_i2c_address;
 
        priv->frequency = frequency;
-       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+       priv->bandwidth = c->bandwidth_hz;
 
        return 5;
 }
index a7fc7e53a5518f6b20edbb7d96d050c8a2a5dbe3..dcfc902c8678be0c64b04989f549639e8114fa47 100644 (file)
@@ -68,15 +68,18 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+/*
+ * Only needed if it actually reads something from the hardware
+ */
+static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe)
 {
        return 0;
 }
 
-static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe)
 {
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -171,10 +174,9 @@ error:
 }
 
 static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Dummy DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 0,
                .frequency_max          = 863250000,
                .frequency_stepsize     = 62500,
@@ -203,10 +205,9 @@ static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
 };
 
 static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A },
        .info = {
                .name                   = "Dummy DVB-C",
-               .type                   = FE_QAM,
                .frequency_stepsize     = 62500,
                .frequency_min          = 51000000,
                .frequency_max          = 858000000,
@@ -233,10 +234,9 @@ static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
 };
 
 static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "Dummy DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 250,           /* kHz for QPSK frontends */
index 2414dc6ee5d992f29c387788e452fb35736e088c..c56fddbf53b77b56b5cb9ea4c1ca34e59e6e96d0 100644 (file)
@@ -76,19 +76,19 @@ static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
        return 0;
 }
 
-static int ec100_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int ec100_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct ec100_state *state = fe->demodulator_priv;
        int ret;
        u8 tmp, tmp2;
 
-       deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
-               params->u.ofdm.bandwidth);
+       deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency,
+               c->bandwidth_hz);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
-               fe->ops.tuner_ops.set_params(fe, params);
+               fe->ops.tuner_ops.set_params(fe);
 
        ret = ec100_write_reg(state, 0x04, 0x06);
        if (ret)
@@ -108,16 +108,16 @@ static int ec100_set_frontend(struct dvb_frontend *fe,
           B 0x1b | 0xb7 | 0x00 | 0x49
           B 0x1c | 0x55 | 0x64 | 0x72 */
 
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                tmp = 0xb7;
                tmp2 = 0x55;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                tmp = 0x00;
                tmp2 = 0x64;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
        default:
                tmp = 0x49;
                tmp2 = 0x72;
@@ -306,9 +306,9 @@ error:
 EXPORT_SYMBOL(ec100_attach);
 
 static struct dvb_frontend_ops ec100_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "E3C EC100 DVB-T",
-               .type = FE_OFDM,
                .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 |
diff --git a/drivers/media/dvb/frontends/hd29l2.c b/drivers/media/dvb/frontends/hd29l2.c
new file mode 100644 (file)
index 0000000..a003181
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: Antti Palosaari <crope@iki.fi>
+ *
+ *    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 "hd29l2_priv.h"
+
+int hd29l2_debug;
+module_param_named(debug, hd29l2_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+/* write multiple registers */
+static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[2 + len];
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = priv->cfg.i2c_addr,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = 0x00;
+       buf[1] = reg;
+       memcpy(&buf[2], val, len);
+
+       ret = i2c_transfer(priv->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+
+       return ret;
+}
+
+/* read multiple registers */
+static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[2] = { 0x00, reg };
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = priv->cfg.i2c_addr,
+                       .flags = 0,
+                       .len = 2,
+                       .buf = buf,
+               }, {
+                       .addr = priv->cfg.i2c_addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = val,
+               }
+       };
+
+       ret = i2c_transfer(priv->i2c, msg, 2);
+       if (ret == 2) {
+               ret = 0;
+       } else {
+               warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+
+       return ret;
+}
+
+/* write single register */
+static int hd29l2_wr_reg(struct hd29l2_priv *priv, u8 reg, u8 val)
+{
+       return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int hd29l2_rd_reg(struct hd29l2_priv *priv, u8 reg, u8 *val)
+{
+       return hd29l2_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+       int ret, i;
+       u8 tmp;
+
+       ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+       if (ret)
+               return ret;
+
+       tmp &= mask;
+
+       /* find position of the first bit */
+       for (i = 0; i < 8; i++) {
+               if ((mask >> i) & 0x01)
+                       break;
+       }
+       *val = tmp >> i;
+
+       return 0;
+}
+
+static int hd29l2_soft_reset(struct hd29l2_priv *priv)
+{
+       int ret;
+       u8 tmp;
+
+       ret = hd29l2_rd_reg(priv, 0x26, &tmp);
+       if (ret)
+               goto err;
+
+       ret = hd29l2_wr_reg(priv, 0x26, 0x0d);
+       if (ret)
+               goto err;
+
+       usleep_range(10000, 20000);
+
+       ret = hd29l2_wr_reg(priv, 0x26, tmp);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       int ret, i;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 tmp;
+
+       dbg("%s: enable=%d", __func__, enable);
+
+       /* set tuner address for demod */
+       if (!priv->tuner_i2c_addr_programmed && enable) {
+               /* no need to set tuner address every time, once is enough */
+               ret = hd29l2_wr_reg(priv, 0x9d, priv->cfg.tuner_i2c_addr << 1);
+               if (ret)
+                       goto err;
+
+               priv->tuner_i2c_addr_programmed = true;
+       }
+
+       /* open / close gate */
+       ret = hd29l2_wr_reg(priv, 0x9f, enable);
+       if (ret)
+               goto err;
+
+       /* wait demod ready */
+       for (i = 10; i; i--) {
+               ret = hd29l2_rd_reg(priv, 0x9e, &tmp);
+               if (ret)
+                       goto err;
+
+               if (tmp == enable)
+                       break;
+
+               usleep_range(5000, 10000);
+       }
+
+       dbg("%s: loop=%d", __func__, i);
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       int ret;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 buf[2];
+
+       *status = 0;
+
+       ret = hd29l2_rd_reg(priv, 0x05, &buf[0]);
+       if (ret)
+               goto err;
+
+       if (buf[0] & 0x01) {
+               /* full lock */
+               *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+                       FE_HAS_SYNC | FE_HAS_LOCK;
+       } else {
+               ret = hd29l2_rd_reg(priv, 0x0d, &buf[1]);
+               if (ret)
+                       goto err;
+
+               if ((buf[1] & 0xfe) == 0x78)
+                       /* partial lock */
+                       *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+                               FE_HAS_VITERBI | FE_HAS_SYNC;
+       }
+
+       priv->fe_status = *status;
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       int ret;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 buf[2];
+       u16 tmp;
+
+       if (!(priv->fe_status & FE_HAS_LOCK)) {
+               *snr = 0;
+               ret = 0;
+               goto err;
+       }
+
+       ret = hd29l2_rd_regs(priv, 0x0b, buf, 2);
+       if (ret)
+               goto err;
+
+       tmp = (buf[0] << 8) | buf[1];
+
+       /* report SNR in dB * 10 */
+       #define LOG10_20736_24 72422627 /* log10(20736) << 24 */
+       if (tmp)
+               *snr = (LOG10_20736_24 - intlog10(tmp)) / ((1 << 24) / 100);
+       else
+               *snr = 0;
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       int ret;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 buf[2];
+       u16 tmp;
+
+       *strength = 0;
+
+       ret = hd29l2_rd_regs(priv, 0xd5, buf, 2);
+       if (ret)
+               goto err;
+
+       tmp = buf[0] << 8 | buf[1];
+       tmp = ~tmp & 0x0fff;
+
+       /* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+       *strength = tmp * 0xffff / 0x0fff;
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       int ret;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 buf[2];
+
+       if (!(priv->fe_status & FE_HAS_SYNC)) {
+               *ber = 0;
+               ret = 0;
+               goto err;
+       }
+
+       ret = hd29l2_rd_regs(priv, 0xd9, buf, 2);
+       if (ret) {
+               *ber = 0;
+               goto err;
+       }
+
+       /* LDPC BER */
+       *ber = ((buf[0] & 0x0f) << 8) | buf[1];
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       /* no way to read? */
+       *ucblocks = 0;
+       return 0;
+}
+
+static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
+{
+       int ret, i;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u8 tmp, buf[3];
+       u8 modulation, carrier, guard_interval, interleave, code_rate;
+       u64 num64;
+       u32 if_freq, if_ctl;
+       bool auto_mode;
+
+       dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \
+               "modulation=%d inversion=%d fec_inner=%d guard_interval=%d",
+                __func__,
+               c->delivery_system, c->frequency, c->bandwidth_hz,
+               c->modulation, c->inversion, c->fec_inner, c->guard_interval);
+
+       /* as for now we detect always params automatically */
+       auto_mode = true;
+
+       /* program tuner */
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe);
+
+       /* get and program IF */
+       if (fe->ops.tuner_ops.get_if_frequency)
+               fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+       else
+               if_freq = 0;
+
+       if (if_freq) {
+               /* normal IF */
+
+               /* calc IF control value */
+               num64 = if_freq;
+               num64 *= 0x800000;
+               num64 = div_u64(num64, HD29L2_XTAL);
+               num64 -= 0x800000;
+               if_ctl = num64;
+
+               tmp = 0xfc; /* tuner type normal */
+       } else {
+               /* zero IF */
+               if_ctl = 0;
+               tmp = 0xfe; /* tuner type Zero-IF */
+       }
+
+       buf[0] = ((if_ctl >>  0) & 0xff);
+       buf[1] = ((if_ctl >>  8) & 0xff);
+       buf[2] = ((if_ctl >> 16) & 0xff);
+
+       /* program IF control */
+       ret = hd29l2_wr_regs(priv, 0x14, buf, 3);
+       if (ret)
+               goto err;
+
+       /* program tuner type */
+       ret = hd29l2_wr_reg(priv, 0xab, tmp);
+       if (ret)
+               goto err;
+
+       dbg("%s: if_freq=%d if_ctl=%x", __func__, if_freq, if_ctl);
+
+       if (auto_mode) {
+               /*
+                * use auto mode
+                */
+
+               /* disable quick mode */
+               ret = hd29l2_wr_reg_mask(priv, 0xac, 0 << 7, 0x80);
+               if (ret)
+                       goto err;
+
+               ret = hd29l2_wr_reg_mask(priv, 0x82, 1 << 1, 0x02);
+               if (ret)
+                       goto err;
+
+               /* enable auto mode */
+               ret = hd29l2_wr_reg_mask(priv, 0x7d, 1 << 6, 0x40);
+               if (ret)
+                       goto err;
+
+               ret = hd29l2_wr_reg_mask(priv, 0x81, 1 << 3, 0x08);
+               if (ret)
+                       goto err;
+
+               /* soft reset */
+               ret = hd29l2_soft_reset(priv);
+               if (ret)
+                       goto err;
+
+               /* detect modulation */
+               for (i = 30; i; i--) {
+                       msleep(100);
+
+                       ret = hd29l2_rd_reg(priv, 0x0d, &tmp);
+                       if (ret)
+                               goto err;
+
+                       if ((((tmp & 0xf0) >= 0x10) &&
+                               ((tmp & 0x0f) == 0x08)) || (tmp >= 0x2c))
+                               break;
+               }
+
+               dbg("%s: loop=%d", __func__, i);
+
+               if (i == 0)
+                       /* detection failed */
+                       return DVBFE_ALGO_SEARCH_FAILED;
+
+               /* read modulation */
+               ret = hd29l2_rd_reg_mask(priv, 0x7d, &modulation, 0x07);
+               if (ret)
+                       goto err;
+       } else {
+               /*
+                * use manual mode
+                */
+
+               modulation = HD29L2_QAM64;
+               carrier = HD29L2_CARRIER_MULTI;
+               guard_interval = HD29L2_PN945;
+               interleave = HD29L2_INTERLEAVER_420;
+               code_rate = HD29L2_CODE_RATE_08;
+
+               tmp = (code_rate << 3) | modulation;
+               ret = hd29l2_wr_reg_mask(priv, 0x7d, tmp, 0x5f);
+               if (ret)
+                       goto err;
+
+               tmp = (carrier << 2) | guard_interval;
+               ret = hd29l2_wr_reg_mask(priv, 0x81, tmp, 0x0f);
+               if (ret)
+                       goto err;
+
+               tmp = interleave;
+               ret = hd29l2_wr_reg_mask(priv, 0x82, tmp, 0x03);
+               if (ret)
+                       goto err;
+       }
+
+       /* ensure modulation validy */
+       /* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */
+       if (modulation > (ARRAY_SIZE(reg_mod_vals_tab[0].val) - 1)) {
+               dbg("%s: modulation=%d not valid", __func__, modulation);
+               goto err;
+       }
+
+       /* program registers according to modulation */
+       for (i = 0; i < ARRAY_SIZE(reg_mod_vals_tab); i++) {
+               ret = hd29l2_wr_reg(priv, reg_mod_vals_tab[i].reg,
+                       reg_mod_vals_tab[i].val[modulation]);
+               if (ret)
+                       goto err;
+       }
+
+       /* read guard interval */
+       ret = hd29l2_rd_reg_mask(priv, 0x81, &guard_interval, 0x03);
+       if (ret)
+               goto err;
+
+       /* read carrier mode */
+       ret = hd29l2_rd_reg_mask(priv, 0x81, &carrier, 0x04);
+       if (ret)
+               goto err;
+
+       dbg("%s: modulation=%d guard_interval=%d carrier=%d",
+               __func__, modulation, guard_interval, carrier);
+
+       if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) &&
+               (guard_interval == HD29L2_PN945)) {
+               dbg("%s: C=3780 && QAM64 && PN945", __func__);
+
+               ret = hd29l2_wr_reg(priv, 0x42, 0x33);
+               if (ret)
+                       goto err;
+
+               ret = hd29l2_wr_reg(priv, 0xdd, 0x01);
+               if (ret)
+                       goto err;
+       }
+
+       usleep_range(10000, 20000);
+
+       /* soft reset */
+       ret = hd29l2_soft_reset(priv);
+       if (ret)
+               goto err;
+
+       /* wait demod lock */
+       for (i = 30; i; i--) {
+               msleep(100);
+
+               /* read lock bit */
+               ret = hd29l2_rd_reg_mask(priv, 0x05, &tmp, 0x01);
+               if (ret)
+                       goto err;
+
+               if (tmp)
+                       break;
+       }
+
+       dbg("%s: loop=%d", __func__, i);
+
+       if (i == 0)
+               return DVBFE_ALGO_SEARCH_AGAIN;
+
+       return DVBFE_ALGO_SEARCH_SUCCESS;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int hd29l2_get_frontend_algo(struct dvb_frontend *fe)
+{
+       return DVBFE_ALGO_CUSTOM;
+}
+
+static int hd29l2_get_frontend(struct dvb_frontend *fe)
+{
+       int ret;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u8 buf[3];
+       u32 if_ctl;
+       char *str_constellation, *str_code_rate, *str_constellation_code_rate,
+               *str_guard_interval, *str_carrier, *str_guard_interval_carrier,
+               *str_interleave, *str_interleave_;
+
+       ret = hd29l2_rd_reg(priv, 0x7d, &buf[0]);
+       if (ret)
+               goto err;
+
+       ret = hd29l2_rd_regs(priv, 0x81, &buf[1], 2);
+       if (ret)
+               goto err;
+
+       /* constellation, 0x7d[2:0] */
+       switch ((buf[0] >> 0) & 0x07) {
+       case 0: /* QAM4NR */
+               str_constellation = "QAM4NR";
+               c->modulation = QAM_AUTO; /* FIXME */
+               break;
+       case 1: /* QAM4 */
+               str_constellation = "QAM4";
+               c->modulation = QPSK; /* FIXME */
+               break;
+       case 2:
+               str_constellation = "QAM16";
+               c->modulation = QAM_16;
+               break;
+       case 3:
+               str_constellation = "QAM32";
+               c->modulation = QAM_32;
+               break;
+       case 4:
+               str_constellation = "QAM64";
+               c->modulation = QAM_64;
+               break;
+       default:
+               str_constellation = "?";
+       }
+
+       /* LDPC code rate, 0x7d[4:3] */
+       switch ((buf[0] >> 3) & 0x03) {
+       case 0: /* 0.4 */
+               str_code_rate = "0.4";
+               c->fec_inner = FEC_AUTO; /* FIXME */
+               break;
+       case 1: /* 0.6 */
+               str_code_rate = "0.6";
+               c->fec_inner = FEC_3_5;
+               break;
+       case 2: /* 0.8 */
+               str_code_rate = "0.8";
+               c->fec_inner = FEC_4_5;
+               break;
+       default:
+               str_code_rate = "?";
+       }
+
+       /* constellation & code rate set, 0x7d[6] */
+       switch ((buf[0] >> 6) & 0x01) {
+       case 0:
+               str_constellation_code_rate = "manual";
+               break;
+       case 1:
+               str_constellation_code_rate = "auto";
+               break;
+       default:
+               str_constellation_code_rate = "?";
+       }
+
+       /* frame header, 0x81[1:0] */
+       switch ((buf[1] >> 0) & 0x03) {
+       case 0: /* PN945 */
+               str_guard_interval = "PN945";
+               c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+               break;
+       case 1: /* PN595 */
+               str_guard_interval = "PN595";
+               c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+               break;
+       case 2: /* PN420 */
+               str_guard_interval = "PN420";
+               c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+               break;
+       default:
+               str_guard_interval = "?";
+       }
+
+       /* carrier, 0x81[2] */
+       switch ((buf[1] >> 2) & 0x01) {
+       case 0:
+               str_carrier = "C=1";
+               break;
+       case 1:
+               str_carrier = "C=3780";
+               break;
+       default:
+               str_carrier = "?";
+       }
+
+       /* frame header & carrier set, 0x81[3] */
+       switch ((buf[1] >> 3) & 0x01) {
+       case 0:
+               str_guard_interval_carrier = "manual";
+               break;
+       case 1:
+               str_guard_interval_carrier = "auto";
+               break;
+       default:
+               str_guard_interval_carrier = "?";
+       }
+
+       /* interleave, 0x82[0] */
+       switch ((buf[2] >> 0) & 0x01) {
+       case 0:
+               str_interleave = "M=720";
+               break;
+       case 1:
+               str_interleave = "M=240";
+               break;
+       default:
+               str_interleave = "?";
+       }
+
+       /* interleave set, 0x82[1] */
+       switch ((buf[2] >> 1) & 0x01) {
+       case 0:
+               str_interleave_ = "manual";
+               break;
+       case 1:
+               str_interleave_ = "auto";
+               break;
+       default:
+               str_interleave_ = "?";
+       }
+
+       /*
+        * We can read out current detected NCO and use that value next
+        * time instead of calculating new value from targed IF.
+        * I think it will not effect receiver sensitivity but gaining lock
+        * after tune could be easier...
+        */
+       ret = hd29l2_rd_regs(priv, 0xb1, &buf[0], 3);
+       if (ret)
+               goto err;
+
+       if_ctl = (buf[0] << 16) | ((buf[1] - 7) << 8) | buf[2];
+
+       dbg("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x", __func__,
+               str_constellation, str_code_rate, str_constellation_code_rate,
+               str_guard_interval, str_carrier, str_guard_interval_carrier,
+               str_interleave, str_interleave_, if_ctl);
+
+       return 0;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static int hd29l2_init(struct dvb_frontend *fe)
+{
+       int ret, i;
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       u8 tmp;
+       static const struct reg_val tab[] = {
+               { 0x3a, 0x06 },
+               { 0x3b, 0x03 },
+               { 0x3c, 0x04 },
+               { 0xaf, 0x06 },
+               { 0xb0, 0x1b },
+               { 0x80, 0x64 },
+               { 0x10, 0x38 },
+       };
+
+       dbg("%s:", __func__);
+
+       /* reset demod */
+       /* it is recommended to HW reset chip using RST_N pin */
+       if (fe->callback) {
+               ret = fe->callback(fe, DVB_FRONTEND_COMPONENT_DEMOD, 0, 0);
+               if (ret)
+                       goto err;
+
+               /* reprogramming needed because HW reset clears registers */
+               priv->tuner_i2c_addr_programmed = false;
+       }
+
+       /* init */
+       for (i = 0; i < ARRAY_SIZE(tab); i++) {
+               ret = hd29l2_wr_reg(priv, tab[i].reg, tab[i].val);
+               if (ret)
+                       goto err;
+       }
+
+       /* TS params */
+       ret = hd29l2_rd_reg(priv, 0x36, &tmp);
+       if (ret)
+               goto err;
+
+       tmp &= 0x1b;
+       tmp |= priv->cfg.ts_mode;
+       ret = hd29l2_wr_reg(priv, 0x36, tmp);
+       if (ret)
+               goto err;
+
+       ret = hd29l2_rd_reg(priv, 0x31, &tmp);
+       tmp &= 0xef;
+
+       if (!(priv->cfg.ts_mode >> 7))
+               /* set b4 for serial TS */
+               tmp |= 0x10;
+
+       ret = hd29l2_wr_reg(priv, 0x31, tmp);
+       if (ret)
+               goto err;
+
+       return ret;
+err:
+       dbg("%s: failed=%d", __func__, ret);
+       return ret;
+}
+
+static void hd29l2_release(struct dvb_frontend *fe)
+{
+       struct hd29l2_priv *priv = fe->demodulator_priv;
+       kfree(priv);
+}
+
+static struct dvb_frontend_ops hd29l2_ops;
+
+struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+       struct i2c_adapter *i2c)
+{
+       int ret;
+       struct hd29l2_priv *priv = NULL;
+       u8 tmp;
+
+       /* allocate memory for the internal state */
+       priv = kzalloc(sizeof(struct hd29l2_priv), GFP_KERNEL);
+       if (priv == NULL)
+               goto err;
+
+       /* setup the state */
+       priv->i2c = i2c;
+       memcpy(&priv->cfg, config, sizeof(struct hd29l2_config));
+
+
+       /* check if the demod is there */
+       ret = hd29l2_rd_reg(priv, 0x00, &tmp);
+       if (ret)
+               goto err;
+
+       /* create dvb_frontend */
+       memcpy(&priv->fe.ops, &hd29l2_ops, sizeof(struct dvb_frontend_ops));
+       priv->fe.demodulator_priv = priv;
+
+       return &priv->fe;
+err:
+       kfree(priv);
+       return NULL;
+}
+EXPORT_SYMBOL(hd29l2_attach);
+
+static struct dvb_frontend_ops hd29l2_ops = {
+       .delsys = { SYS_DVBT },
+       .info = {
+               .name = "HDIC HD29L2 DMB-TH",
+               .frequency_min = 474000000,
+               .frequency_max = 858000000,
+               .frequency_stepsize = 10000,
+               .caps = FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK |
+                       FE_CAN_QAM_16 |
+                       FE_CAN_QAM_32 |
+                       FE_CAN_QAM_64 |
+                       FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_BANDWIDTH_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_HIERARCHY_AUTO |
+                       FE_CAN_RECOVER
+       },
+
+       .release = hd29l2_release,
+
+       .init = hd29l2_init,
+
+       .get_frontend_algo = hd29l2_get_frontend_algo,
+       .search = hd29l2_search,
+       .get_frontend = hd29l2_get_frontend,
+
+       .read_status = hd29l2_read_status,
+       .read_snr = hd29l2_read_snr,
+       .read_signal_strength = hd29l2_read_signal_strength,
+       .read_ber = hd29l2_read_ber,
+       .read_ucblocks = hd29l2_read_ucblocks,
+
+       .i2c_gate_ctrl = hd29l2_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("HDIC HD29L2 DMB-TH demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/hd29l2.h b/drivers/media/dvb/frontends/hd29l2.h
new file mode 100644 (file)
index 0000000..a7a6443
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: Antti Palosaari <crope@iki.fi>
+ *
+ *    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 HD29L2_H
+#define HD29L2_H
+
+#include <linux/dvb/frontend.h>
+
+struct hd29l2_config {
+       /*
+        * demodulator I2C address
+        */
+       u8 i2c_addr;
+
+       /*
+        * tuner I2C address
+        * only needed when tuner is behind demod I2C-gate
+        */
+       u8 tuner_i2c_addr;
+
+       /*
+        * TS settings
+        */
+#define HD29L2_TS_SERIAL            0x00
+#define HD29L2_TS_PARALLEL          0x80
+#define HD29L2_TS_CLK_NORMAL        0x40
+#define HD29L2_TS_CLK_INVERTED      0x00
+#define HD29L2_TS_CLK_GATED         0x20
+#define HD29L2_TS_CLK_FREE          0x00
+       u8 ts_mode;
+};
+
+
+#if defined(CONFIG_DVB_HD29L2) || \
+       (defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
+extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+       struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *hd29l2_attach(
+const struct hd29l2_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif /* HD29L2_H */
diff --git a/drivers/media/dvb/frontends/hd29l2_priv.h b/drivers/media/dvb/frontends/hd29l2_priv.h
new file mode 100644 (file)
index 0000000..ba16dc3
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: Antti Palosaari <crope@iki.fi>
+ *
+ *    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 HD29L2_PRIV
+#define HD29L2_PRIV
+
+#include <linux/dvb/version.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "hd29l2.h"
+
+#define LOG_PREFIX "hd29l2"
+
+#undef dbg
+#define dbg(f, arg...) \
+       if (hd29l2_debug) \
+               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+#define HD29L2_XTAL 30400000 /* Hz */
+
+
+#define HD29L2_QAM4NR 0x00
+#define HD29L2_QAM4   0x01
+#define HD29L2_QAM16  0x02
+#define HD29L2_QAM32  0x03
+#define HD29L2_QAM64  0x04
+
+#define HD29L2_CODE_RATE_04 0x00
+#define HD29L2_CODE_RATE_06 0x08
+#define HD29L2_CODE_RATE_08 0x10
+
+#define HD29L2_PN945 0x00
+#define HD29L2_PN595 0x01
+#define HD29L2_PN420 0x02
+
+#define HD29L2_CARRIER_SINGLE 0x00
+#define HD29L2_CARRIER_MULTI  0x01
+
+#define HD29L2_INTERLEAVER_720 0x00
+#define HD29L2_INTERLEAVER_420 0x01
+
+struct reg_val {
+       u8 reg;
+       u8 val;
+};
+
+struct reg_mod_vals {
+       u8 reg;
+       u8 val[5];
+};
+
+struct hd29l2_priv {
+       struct i2c_adapter *i2c;
+       struct dvb_frontend fe;
+       struct hd29l2_config cfg;
+       u8 tuner_i2c_addr_programmed:1;
+
+       fe_status_t fe_status;
+};
+
+static const struct reg_mod_vals reg_mod_vals_tab[] = {
+       /* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */
+       { 0x01, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+       { 0x02, { 0x07, 0x07, 0x07, 0x07, 0x07 } },
+       { 0x03, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+       { 0x04, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x05, { 0x61, 0x60, 0x60, 0x61, 0x60 } },
+       { 0x06, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+       { 0x07, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+       { 0x08, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x09, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x0a, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+       { 0x0d, { 0x78, 0x78, 0x88, 0x78, 0x78 } },
+       { 0x0e, { 0xa0, 0x90, 0xa0, 0xa0, 0xa0 } },
+       { 0x0f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x10, { 0xa0, 0xa0, 0x58, 0x38, 0x38 } },
+       { 0x11, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x12, { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a } },
+       { 0x13, { 0xa2, 0xa2, 0xa2, 0xa2, 0xa2 } },
+       { 0x17, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+       { 0x18, { 0x21, 0x21, 0x42, 0x52, 0x42 } },
+       { 0x19, { 0x21, 0x21, 0x62, 0x72, 0x62 } },
+       { 0x1a, { 0x32, 0x43, 0xa9, 0xb9, 0xa9 } },
+       { 0x1b, { 0x32, 0x43, 0xb9, 0xd8, 0xb9 } },
+       { 0x1c, { 0x02, 0x02, 0x03, 0x02, 0x03 } },
+       { 0x1d, { 0x0c, 0x0c, 0x01, 0x02, 0x02 } },
+       { 0x1e, { 0x02, 0x02, 0x02, 0x01, 0x02 } },
+       { 0x1f, { 0x02, 0x02, 0x01, 0x02, 0x04 } },
+       { 0x20, { 0x01, 0x02, 0x01, 0x01, 0x01 } },
+       { 0x21, { 0x08, 0x08, 0x0a, 0x0a, 0x0a } },
+       { 0x22, { 0x06, 0x06, 0x04, 0x05, 0x05 } },
+       { 0x23, { 0x06, 0x06, 0x05, 0x03, 0x05 } },
+       { 0x24, { 0x08, 0x08, 0x05, 0x07, 0x07 } },
+       { 0x25, { 0x16, 0x10, 0x10, 0x0a, 0x10 } },
+       { 0x26, { 0x14, 0x14, 0x04, 0x04, 0x04 } },
+       { 0x27, { 0x58, 0x58, 0x58, 0x5c, 0x58 } },
+       { 0x28, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0x29, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0x2a, { 0x08, 0x0a, 0x08, 0x08, 0x08 } },
+       { 0x2b, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+       { 0x2c, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+       { 0x2d, { 0x05, 0x06, 0x06, 0x06, 0x06 } },
+       { 0x2e, { 0x21, 0x21, 0x21, 0x21, 0x21 } },
+       { 0x2f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x30, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+       { 0x33, { 0xb7, 0xb7, 0xb7, 0xb7, 0xb7 } },
+       { 0x34, { 0x81, 0x81, 0x81, 0x81, 0x81 } },
+       { 0x35, { 0x80, 0x80, 0x80, 0x80, 0x80 } },
+       { 0x37, { 0x70, 0x70, 0x70, 0x70, 0x70 } },
+       { 0x38, { 0x04, 0x04, 0x02, 0x02, 0x02 } },
+       { 0x39, { 0x07, 0x07, 0x05, 0x05, 0x05 } },
+       { 0x3a, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+       { 0x3b, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+       { 0x3c, { 0x07, 0x06, 0x04, 0x04, 0x04 } },
+       { 0x3d, { 0xf0, 0xf0, 0xf0, 0xf0, 0x80 } },
+       { 0x3e, { 0x60, 0x60, 0x60, 0x60, 0xff } },
+       { 0x3f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x40, { 0x5b, 0x5b, 0x5b, 0x57, 0x50 } },
+       { 0x41, { 0x30, 0x30, 0x30, 0x30, 0x18 } },
+       { 0x42, { 0x20, 0x20, 0x20, 0x00, 0x30 } },
+       { 0x43, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x44, { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f } },
+       { 0x45, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x46, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0x47, { 0x00, 0x00, 0x95, 0x00, 0x95 } },
+       { 0x48, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+       { 0x49, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+       { 0x4a, { 0x40, 0x40, 0x33, 0x11, 0x11 } },
+       { 0x4b, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+       { 0x4c, { 0x40, 0x40, 0x99, 0x11, 0x11 } },
+       { 0x4d, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+       { 0x4e, { 0x40, 0x40, 0x66, 0x77, 0x77 } },
+       { 0x4f, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+       { 0x50, { 0x40, 0x40, 0x88, 0x33, 0x11 } },
+       { 0x51, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+       { 0x52, { 0x40, 0x40, 0x88, 0x02, 0x02 } },
+       { 0x53, { 0x40, 0x40, 0x00, 0x02, 0x02 } },
+       { 0x54, { 0x00, 0x00, 0x88, 0x33, 0x33 } },
+       { 0x55, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+       { 0x56, { 0x00, 0x00, 0x00, 0x0b, 0x00 } },
+       { 0x57, { 0x40, 0x40, 0x0a, 0x0b, 0x0a } },
+       { 0x58, { 0xaa, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x59, { 0x7a, 0x40, 0x02, 0x02, 0x02 } },
+       { 0x5a, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+       { 0x5b, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+       { 0x5c, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+       { 0x5d, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+       { 0x5e, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+       { 0x5f, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+       { 0x60, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+       { 0x61, { 0x40, 0x40, 0x10, 0x30, 0x30 } },
+       { 0x62, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+       { 0x63, { 0x40, 0x40, 0x05, 0x30, 0x30 } },
+       { 0x64, { 0x40, 0x40, 0x06, 0x00, 0x30 } },
+       { 0x65, { 0x40, 0x40, 0x06, 0x08, 0x30 } },
+       { 0x66, { 0x40, 0x40, 0x00, 0x00, 0x20 } },
+       { 0x67, { 0x40, 0x40, 0x01, 0x04, 0x20 } },
+       { 0x68, { 0x00, 0x00, 0x30, 0x00, 0x20 } },
+       { 0x69, { 0xa0, 0xa0, 0x00, 0x08, 0x20 } },
+       { 0x6a, { 0x00, 0x00, 0x30, 0x00, 0x25 } },
+       { 0x6b, { 0xa0, 0xa0, 0x00, 0x06, 0x25 } },
+       { 0x6c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x6d, { 0xa0, 0x60, 0x0c, 0x03, 0x0c } },
+       { 0x6e, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x6f, { 0xa0, 0x60, 0x04, 0x01, 0x04 } },
+       { 0x70, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+       { 0x71, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+       { 0x72, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+       { 0x73, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+       { 0x74, { 0x06, 0x06, 0x09, 0x05, 0x05 } },
+       { 0x75, { 0x06, 0x06, 0x0a, 0x10, 0x10 } },
+       { 0x76, { 0x10, 0x10, 0x06, 0x0a, 0x0a } },
+       { 0x77, { 0x12, 0x18, 0x28, 0x10, 0x28 } },
+       { 0x78, { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 } },
+       { 0x79, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+       { 0x7a, { 0x02, 0x02, 0x01, 0x04, 0x03 } },
+       { 0x7b, { 0x01, 0x02, 0x03, 0x03, 0x03 } },
+       { 0x7c, { 0x28, 0x28, 0x28, 0x28, 0x28 } },
+       { 0x7f, { 0x25, 0x92, 0x5f, 0x17, 0x2d } },
+       { 0x80, { 0x64, 0x64, 0x64, 0x74, 0x64 } },
+       { 0x83, { 0x06, 0x03, 0x04, 0x04, 0x04 } },
+       { 0x84, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+       { 0x85, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+       { 0x86, { 0x00, 0x00, 0x11, 0x11, 0x11 } },
+       { 0x87, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+       { 0x88, { 0x09, 0x09, 0x09, 0x09, 0x09 } },
+       { 0x89, { 0x20, 0x20, 0x30, 0x20, 0x20 } },
+       { 0x8a, { 0x03, 0x03, 0x02, 0x03, 0x02 } },
+       { 0x8b, { 0x00, 0x07, 0x09, 0x00, 0x09 } },
+       { 0x8c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x8d, { 0x4f, 0x4f, 0x4f, 0x3f, 0x4f } },
+       { 0x8e, { 0xf0, 0xf0, 0x60, 0xf0, 0xa0 } },
+       { 0x8f, { 0xe8, 0xe8, 0xe8, 0xe8, 0xe8 } },
+       { 0x90, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+       { 0x91, { 0x40, 0x40, 0x70, 0x70, 0x10 } },
+       { 0x92, { 0x00, 0x00, 0x00, 0x00, 0x04 } },
+       { 0x93, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+       { 0x94, { 0x00, 0x00, 0x00, 0x00, 0x03 } },
+       { 0x95, { 0x09, 0x09, 0x47, 0x47, 0x47 } },
+       { 0x96, { 0x80, 0xa0, 0xa0, 0x40, 0xa0 } },
+       { 0x97, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+       { 0x98, { 0x50, 0x50, 0x50, 0x30, 0x50 } },
+       { 0x99, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+       { 0x9a, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0x9b, { 0x40, 0x40, 0x40, 0x30, 0x40 } },
+       { 0x9c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa0, { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 } },
+       { 0xa1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa2, { 0x30, 0x30, 0x00, 0x30, 0x00 } },
+       { 0xa3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa5, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xa8, { 0x77, 0x77, 0x77, 0x77, 0x77 } },
+       { 0xa9, { 0x02, 0x02, 0x02, 0x02, 0x02 } },
+       { 0xaa, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+       { 0xac, { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f } },
+       { 0xad, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+       { 0xae, { 0x78, 0x78, 0x78, 0x78, 0x78 } },
+       { 0xaf, { 0x06, 0x06, 0x06, 0x06, 0x07 } },
+       { 0xb0, { 0x1b, 0x1b, 0x1b, 0x19, 0x1b } },
+       { 0xb1, { 0x18, 0x17, 0x17, 0x18, 0x17 } },
+       { 0xb2, { 0x35, 0x82, 0x82, 0x38, 0x82 } },
+       { 0xb3, { 0xb6, 0xce, 0xc7, 0x5c, 0xb0 } },
+       { 0xb4, { 0x3f, 0x3e, 0x3e, 0x3f, 0x3e } },
+       { 0xb5, { 0x70, 0x58, 0x50, 0x68, 0x50 } },
+       { 0xb6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xb7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xb8, { 0x03, 0x03, 0x01, 0x01, 0x01 } },
+       { 0xb9, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xba, { 0x06, 0x06, 0x0a, 0x05, 0x0a } },
+       { 0xbb, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xbc, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xbd, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xbe, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xbf, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc3, { 0x00, 0x00, 0x88, 0x66, 0x88 } },
+       { 0xc4, { 0x10, 0x10, 0x00, 0x00, 0x00 } },
+       { 0xc5, { 0x00, 0x00, 0x44, 0x60, 0x44 } },
+       { 0xc6, { 0x10, 0x0a, 0x00, 0x00, 0x00 } },
+       { 0xc7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc8, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xc9, { 0x90, 0x04, 0x00, 0x00, 0x00 } },
+       { 0xca, { 0x90, 0x08, 0x01, 0x01, 0x01 } },
+       { 0xcb, { 0xa0, 0x04, 0x00, 0x44, 0x00 } },
+       { 0xcc, { 0xa0, 0x10, 0x03, 0x00, 0x03 } },
+       { 0xcd, { 0x06, 0x06, 0x06, 0x05, 0x06 } },
+       { 0xce, { 0x05, 0x05, 0x01, 0x01, 0x01 } },
+       { 0xcf, { 0x40, 0x20, 0x18, 0x18, 0x18 } },
+       { 0xd0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xd1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xd2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xd3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xd4, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+       { 0xd5, { 0x05, 0x05, 0x05, 0x03, 0x05 } },
+       { 0xd6, { 0xac, 0x22, 0xca, 0x8f, 0xca } },
+       { 0xd7, { 0x20, 0x20, 0x20, 0x20, 0x20 } },
+       { 0xd8, { 0x01, 0x01, 0x01, 0x01, 0x01 } },
+       { 0xd9, { 0x00, 0x00, 0x0f, 0x00, 0x0f } },
+       { 0xda, { 0x00, 0xff, 0xff, 0x0e, 0xff } },
+       { 0xdb, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0xdc, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0xdd, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+       { 0xde, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0xdf, { 0x42, 0x42, 0x44, 0x44, 0x04 } },
+       { 0xe0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xe1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xe2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xe3, { 0x00, 0x00, 0x26, 0x06, 0x26 } },
+       { 0xe4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xe5, { 0x01, 0x0a, 0x01, 0x01, 0x01 } },
+       { 0xe6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xe7, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+       { 0xe8, { 0x63, 0x63, 0x63, 0x63, 0x63 } },
+       { 0xe9, { 0x59, 0x59, 0x59, 0x59, 0x59 } },
+       { 0xea, { 0x80, 0x80, 0x20, 0x80, 0x80 } },
+       { 0xeb, { 0x37, 0x37, 0x78, 0x37, 0x77 } },
+       { 0xec, { 0x1f, 0x1f, 0x25, 0x25, 0x25 } },
+       { 0xed, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+       { 0xee, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+       { 0xef, { 0x70, 0x70, 0x58, 0x38, 0x58 } },
+       { 0xf0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+};
+
+#endif /* HD29L2_PRIV */
index 1c6fb4b662556ddd18bfdf8ec897ad9d268bec92..93b086ea7e1cda446d9197d5af938194a590aa2b 100644 (file)
@@ -22,126 +22,126 @@ struct adctable { u32 adcFrequency;
 /* clock and coeff tables only table 3 is used with IT9137*/
 /* TODO other tables relate AF9035 may be removed */
 static struct adctable tab1[] = {
-       {       20156250, BANDWIDTH_6_MHZ,
+       {       20156250, 6000000,
                0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
                0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c      },
-       {       20156250, BANDWIDTH_7_MHZ,
+       {       20156250, 7000000,
                0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
                0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196      },
-       {       20156250, BANDWIDTH_8_MHZ,
+       {       20156250, 8000000,
                0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
                0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0      },
-       {       20156250, BANDWIDTH_5_MHZ,
+       {       20156250, 5000000,
                0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
                0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122      }
 };
 
 static struct adctable tab2[] = {
-       {       20187500, BANDWIDTH_6_MHZ,
+       {       20187500, 6000000,
                0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
                0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c      },
-       {       20187500, BANDWIDTH_7_MHZ,
+       {       20187500, 7000000,
                0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
                0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196      },
-       {       20187500, BANDWIDTH_8_MHZ,
+       {       20187500, 8000000,
                0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
                0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0      },
-       {       20187500, BANDWIDTH_5_MHZ,
+       {       20187500, 5000000,
                0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
                0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122      }
 
 };
 
 static struct adctable tab3[] = {
-       {       20250000, BANDWIDTH_6_MHZ,
+       {       20250000, 6000000,
                0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
                0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b      },
-       {       20250000, BANDWIDTH_7_MHZ,
+       {       20250000, 7000000,
                0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
                0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195      },
-       {       20250000, BANDWIDTH_8_MHZ,
+       {       20250000, 8000000,
                0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
                0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce      },
-       {       20250000, BANDWIDTH_5_MHZ,
+       {       20250000, 5000000,
                0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
                0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121      }
 
 };
 
 static struct adctable tab4[] = {
-       {       20583333, BANDWIDTH_6_MHZ,
+       {       20583333, 6000000,
                0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
                0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155      },
-       {       20583333, BANDWIDTH_7_MHZ,
+       {       20583333, 7000000,
                0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
                0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e      },
-       {       20583333, BANDWIDTH_8_MHZ,
+       {       20583333, 8000000,
                0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
                0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7      },
-       {       20583333, BANDWIDTH_5_MHZ,
+       {       20583333, 5000000,
                0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
                0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c      }
 
 };
 
 static struct adctable tab5[] = {
-       {       20416667, BANDWIDTH_6_MHZ,
+       {       20416667, 6000000,
                0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
                0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158      },
-       {       20416667, BANDWIDTH_7_MHZ,
+       {       20416667, 7000000,
                0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
                0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191      },
-       {       20416667, BANDWIDTH_8_MHZ,
+       {       20416667, 8000000,
                0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
                0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb      },
-       {       20416667, BANDWIDTH_5_MHZ,
+       {       20416667, 5000000,
                0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
                0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f      }
 
 };
 
 static struct adctable tab6[] = {
-       {       20480000, BANDWIDTH_6_MHZ,
+       {       20480000, 6000000,
                0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
                0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157      },
-       {       20480000, BANDWIDTH_7_MHZ,
+       {       20480000, 7000000,
                0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
                0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190      },
-       {       20480000, BANDWIDTH_8_MHZ,
+       {       20480000, 8000000,
                0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
                0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9      },
-       {       20480000, BANDWIDTH_5_MHZ,
+       {       20480000, 5000000,
                0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
                0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e      }
 };
 
 static struct adctable tab7[] = {
-       {       20500000, BANDWIDTH_6_MHZ,
+       {       20500000, 6000000,
                0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
                0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157      },
-       {       20500000, BANDWIDTH_7_MHZ,
+       {       20500000, 7000000,
                0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
                0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190      },
-       {       20500000, BANDWIDTH_8_MHZ,
+       {       20500000, 8000000,
                0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
                0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9      },
-       {       20500000, BANDWIDTH_5_MHZ,
+       {       20500000, 5000000,
                0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
                0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d      }
 
 };
 
 static struct adctable tab8[] = {
-       {       20625000, BANDWIDTH_6_MHZ,
+       {       20625000, 6000000,
                0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
                0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154      },
-       {       20625000, BANDWIDTH_7_MHZ,
+       {       20625000, 7000000,
                0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
                0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d      },
-       {       20625000, BANDWIDTH_8_MHZ,
+       {       20625000, 8000000,
                0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
                0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6      },
-       {       20625000, BANDWIDTH_5_MHZ,
+       {       20625000, 5000000,
                0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
                0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c      }
 
@@ -153,8 +153,7 @@ struct table {
 };
 
 static struct table fe_clockTable[] = {
-               {12000000, tab3},       /* FPGA     */
-               {16384000, tab6},       /* 16.38MHz */
+               {12000000, tab3},       /* 12.00MHz */
                {20480000, tab6},       /* 20.48MHz */
                {36000000, tab3},       /* 36.00MHz */
                {30000000, tab1},       /* 30.00MHz */
@@ -164,7 +163,6 @@ static struct table fe_clockTable[] = {
                {34000000, tab2},       /* 34.00MHz */
                {24000000, tab1},       /* 24.00MHz */
                {22000000, tab8},       /* 22.00MHz */
-               {12000000, tab3}        /* 12.00MHz */
 };
 
 /* fe get */
@@ -205,6 +203,10 @@ fe_modulation_t fe_con[] = {
 
 /* Standard demodulator functions */
 static struct it913xset set_solo_fe[] = {
+       {PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+       {PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+       {PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+       {PRO_LINK, GPIOH5_O, {0x01}, 0x01},
        {PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
        {PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
        {PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
@@ -228,13 +230,127 @@ static struct it913xset init_1[] = {
        {PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
        {PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
        {PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+       {PRO_DMOD, 0xec57, {0x00, 0x00}, 0x02},
        {PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
        {PRO_LINK, PADMISCDR8, {0x00}, 0x01},
        {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
 };
 
-/* ---------IT9137 0x38 tuner init---------- */
-static struct it913xset it9137_set[] = {
+
+/* Version 1 types */
+static struct it913xset it9135_v1[] = {
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a}, 0x01},
+       {PRO_DMOD, 0x007e, {0x04}, 0x01},
+       {PRO_DMOD, 0x0081, {0x0a}, 0x01},
+       {PRO_DMOD, 0x008a, {0x01}, 0x01},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06}, 0x01},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009f, {0xe1}, 0x01},
+       {PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+       {PRO_DMOD, 0x00a3, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a5, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a6, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a9, {0x00}, 0x01},
+       {PRO_DMOD, 0x00aa, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00c2, {0x05}, 0x01},
+       {PRO_DMOD, 0x00c6, {0x19}, 0x01},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf016, {0x10}, 0x01},
+       {PRO_DMOD, 0xf017, {0x04}, 0x01},
+       {PRO_DMOD, 0xf018, {0x05}, 0x01},
+       {PRO_DMOD, 0xf019, {0x04}, 0x01},
+       {PRO_DMOD, 0xf01a, {0x05}, 0x01},
+       {PRO_DMOD, 0xf021, {0x03}, 0x01},
+       {PRO_DMOD, 0xf022, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf023, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf02b, {0x00}, 0x01},
+       {PRO_DMOD, 0xf02c, {0x01}, 0x01},
+       {PRO_DMOD, 0xf064, {0x03}, 0x01},
+       {PRO_DMOD, 0xf065, {0xf9}, 0x01},
+       {PRO_DMOD, 0xf066, {0x03}, 0x01},
+       {PRO_DMOD, 0xf067, {0x01}, 0x01},
+       {PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+       {PRO_DMOD, 0xf070, {0x03}, 0x01},
+       {PRO_DMOD, 0xf072, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf073, {0x03}, 0x01},
+       {PRO_DMOD, 0xf078, {0x00}, 0x01},
+       {PRO_DMOD, 0xf087, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+       {PRO_DMOD, 0xf09c, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09d, {0x20}, 0x01},
+       {PRO_DMOD, 0xf09e, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+       {PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14d, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf15b, {0x08}, 0x01},
+       {PRO_DMOD, 0xf15d, {0x03}, 0x01},
+       {PRO_DMOD, 0xf15e, {0x05}, 0x01},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01}, 0x01},
+       {PRO_DMOD, 0xf167, {0x40}, 0x01},
+       {PRO_DMOD, 0xf168, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf17a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf17b, {0x00}, 0x01},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+       {PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+       {PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+       {PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf40f, {0x40}, 0x01},
+       {PRO_DMOD, 0xf410, {0x08}, 0x01},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15}, 0x01},
+       {PRO_DMOD, 0xf562, {0x20}, 0x01},
+       {PRO_DMOD, 0xf5df, {0xfb}, 0x01},
+       {PRO_DMOD, 0xf5e0, {0x00}, 0x01},
+       {PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+       {PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+       {PRO_DMOD, 0xf600, {0x05}, 0x01},
+       {PRO_DMOD, 0xf601, {0x08}, 0x01},
+       {PRO_DMOD, 0xf602, {0x0b}, 0x01},
+       {PRO_DMOD, 0xf603, {0x0e}, 0x01},
+       {PRO_DMOD, 0xf604, {0x11}, 0x01},
+       {PRO_DMOD, 0xf605, {0x14}, 0x01},
+       {PRO_DMOD, 0xf606, {0x17}, 0x01},
+       {PRO_DMOD, 0xf607, {0x1f}, 0x01},
+       {PRO_DMOD, 0xf60e, {0x00}, 0x01},
+       {PRO_DMOD, 0xf60f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf610, {0x32}, 0x01},
+       {PRO_DMOD, 0xf611, {0x10}, 0x01},
+       {PRO_DMOD, 0xf707, {0xfc}, 0x01},
+       {PRO_DMOD, 0xf708, {0x00}, 0x01},
+       {PRO_DMOD, 0xf709, {0x37}, 0x01},
+       {PRO_DMOD, 0xf70a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40}, 0x01},
+       {PRO_DMOD, 0xf810, {0x54}, 0x01},
+       {PRO_DMOD, 0xf811, {0x5a}, 0x01},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_38[] = {
        {PRO_DMOD, 0x0043, {0x00}, 0x01},
        {PRO_DMOD, 0x0046, {0x38}, 0x01},
        {PRO_DMOD, 0x0051, {0x01}, 0x01},
@@ -244,7 +360,7 @@ static struct it913xset it9137_set[] = {
        {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
        {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
        {PRO_DMOD, 0x0081, {    0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
-                               0xd0, 0xc3, 0x01        }, 0x0a},
+                               0xd0, 0xc3, 0x01}, 0x0a},
        {PRO_DMOD, 0x008e, {0x01}, 0x01},
        {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
        {PRO_DMOD, 0x0099, {0x01}, 0x01},
@@ -262,15 +378,25 @@ static struct it913xset it9137_set[] = {
        {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
        {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
        {PRO_DMOD, 0x00fc, {    0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
-                               0x00, 0x02, 0xc8, 0x05, 0x7b    }, 0x0c},
+                               0x00, 0x02, 0xc8, 0x05, 0x7b}, 0x0c},
        {PRO_DMOD, 0x0109, {0x02}, 0x01},
-       {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
-       {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+       {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0x8a, 0xa0}, 0x04},
        {PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
        {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
        {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
        {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
-       {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04},
+       {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8, 0x59}, 0x05},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf085, {0x00, 0x02, 0x00}, 0x03},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
        {PRO_DMOD, 0xf130, {0x04}, 0x01},
        {PRO_DMOD, 0xf132, {0x04}, 0x01},
        {PRO_DMOD, 0xf144, {0x1a}, 0x01},
@@ -301,7 +427,7 @@ static struct it913xset it9137_set[] = {
        {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
        {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
        {PRO_DMOD, 0xf600, {    0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-                               0x1f    }, 0x08},
+                               0x1f}, 0x08},
        {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
        {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
        {PRO_DMOD, 0xf78b, {0x01}, 0x01},
@@ -309,21 +435,605 @@ static struct it913xset it9137_set[] = {
        {PRO_DMOD, 0xf905, {0x01}, 0x01},
        {PRO_DMOD, 0xfb06, {0x03}, 0x01},
        {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-       {PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
-       {PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
-       {PRO_LINK, GPIOH5_O, {0x00}, 0x01},
-       {PRO_LINK, GPIOH5_O, {0x01}, 0x01},
-       {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_51[] = {
+       {PRO_DMOD, 0x0043, {0x00}, 0x01},
+       {PRO_DMOD, 0x0046, {0x51}, 0x01},
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a, 0x06, 0x02}, 0x03},
+       {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+       {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+       {PRO_DMOD, 0x0081, {    0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc0, 0x96,
+                               0xcf, 0xc3, 0x01}, 0x0a},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+       {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+       {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+       {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+       {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+       {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+       {PRO_DMOD, 0x00c4, {0x00}, 0x01},
+       {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+       {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+       {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+       {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+       {PRO_DMOD, 0x00fc, {    0x03, 0x02, 0x02, 0x09, 0x50, 0x7a, 0x77,
+                               0x01, 0x02, 0xb0, 0x02, 0x7a}, 0x0c},
+       {PRO_DMOD, 0x0109, {0x02}, 0x01},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+       {PRO_DMOD, 0x011a, {0xc0, 0x7a, 0xac, 0x8c}, 0x04},
+       {PRO_DMOD, 0x0122, {0x02, 0x70, 0xa4}, 0x03},
+       {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+       {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+       {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+       {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc0, 0x59}, 0x05},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+       {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+       {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+       {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+       {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+       {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+       {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+       {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+       {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+       {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+       {PRO_DMOD, 0xf600, {    0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+                               0x1f}, 0x08},
+       {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+       {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_52[] = {
+       {PRO_DMOD, 0x0043, {0x00}, 0x01},
+       {PRO_DMOD, 0x0046, {0x52}, 0x01},
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0x0068, {0x10}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+       {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xa0, 0x01}, 0x05},
+       {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+       {PRO_DMOD, 0x0081, {    0x0a, 0x12, 0x03, 0x0a, 0x03, 0xb3, 0x97,
+                               0xc0, 0x9e, 0x01}, 0x0a},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+       {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+       {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+       {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+       {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+       {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+       {PRO_DMOD, 0x00c4, {0x00}, 0x01},
+       {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+       {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+       {PRO_DMOD, 0x00f3, {0x05, 0x91, 0x8c}, 0x03},
+       {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+       {PRO_DMOD, 0x00fc, {    0x03, 0x02, 0x02, 0x09, 0x50, 0x74, 0x77,
+                               0x02, 0x02, 0xae, 0x02, 0x6e}, 0x0c},
+       {PRO_DMOD, 0x0109, {0x02}, 0x01},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+       {PRO_DMOD, 0x011a, {0xcd, 0x62, 0xa4, 0x8c}, 0x04},
+       {PRO_DMOD, 0x0122, {0x03, 0x18, 0x9e}, 0x03},
+       {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+       {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+       {PRO_DMOD, 0x0137, {0x00, 0x00, 0x07, 0x00, 0x06}, 0x05},
+       {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xb6, 0x59}, 0x05},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+       {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+       {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+       {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+       {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+       {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+       {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+       {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+       {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+       {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+       {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+                               0x1f}, 0x08},
+       {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+       {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
 };
 
+/* Version 2 types */
+static struct it913xset it9135_v2[] = {
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a}, 0x01},
+       {PRO_DMOD, 0x007e, {0x04}, 0x01},
+       {PRO_DMOD, 0x0081, {0x0a}, 0x01},
+       {PRO_DMOD, 0x008a, {0x01}, 0x01},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06}, 0x01},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009f, {0xe1}, 0x01},
+       {PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+       {PRO_DMOD, 0x00a3, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a5, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a6, {0x01}, 0x01},
+       {PRO_DMOD, 0x00a9, {0x00}, 0x01},
+       {PRO_DMOD, 0x00aa, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00c2, {0x05}, 0x01},
+       {PRO_DMOD, 0x00c6, {0x19}, 0x01},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf02b, {0x00}, 0x01},
+       {PRO_DMOD, 0xf064, {0x03}, 0x01},
+       {PRO_DMOD, 0xf065, {0xf9}, 0x01},
+       {PRO_DMOD, 0xf066, {0x03}, 0x01},
+       {PRO_DMOD, 0xf067, {0x01}, 0x01},
+       {PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+       {PRO_DMOD, 0xf070, {0x03}, 0x01},
+       {PRO_DMOD, 0xf072, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf073, {0x03}, 0x01},
+       {PRO_DMOD, 0xf078, {0x00}, 0x01},
+       {PRO_DMOD, 0xf087, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+       {PRO_DMOD, 0xf09c, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09d, {0x20}, 0x01},
+       {PRO_DMOD, 0xf09e, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+       {PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14d, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf15b, {0x08}, 0x01},
+       {PRO_DMOD, 0xf15d, {0x03}, 0x01},
+       {PRO_DMOD, 0xf15e, {0x05}, 0x01},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01}, 0x01},
+       {PRO_DMOD, 0xf167, {0x40}, 0x01},
+       {PRO_DMOD, 0xf168, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf17a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf17b, {0x00}, 0x01},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+       {PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+       {PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+       {PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf40f, {0x40}, 0x01},
+       {PRO_DMOD, 0xf410, {0x08}, 0x01},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15}, 0x01},
+       {PRO_DMOD, 0xf562, {0x20}, 0x01},
+       {PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+       {PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+       {PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+       {PRO_DMOD, 0xf600, {0x05}, 0x01},
+       {PRO_DMOD, 0xf601, {0x08}, 0x01},
+       {PRO_DMOD, 0xf602, {0x0b}, 0x01},
+       {PRO_DMOD, 0xf603, {0x0e}, 0x01},
+       {PRO_DMOD, 0xf604, {0x11}, 0x01},
+       {PRO_DMOD, 0xf605, {0x14}, 0x01},
+       {PRO_DMOD, 0xf606, {0x17}, 0x01},
+       {PRO_DMOD, 0xf607, {0x1f}, 0x01},
+       {PRO_DMOD, 0xf60e, {0x00}, 0x01},
+       {PRO_DMOD, 0xf60f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf610, {0x32}, 0x01},
+       {PRO_DMOD, 0xf611, {0x10}, 0x01},
+       {PRO_DMOD, 0xf707, {0xfc}, 0x01},
+       {PRO_DMOD, 0xf708, {0x00}, 0x01},
+       {PRO_DMOD, 0xf709, {0x37}, 0x01},
+       {PRO_DMOD, 0xf70a, {0x00}, 0x01},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40}, 0x01},
+       {PRO_DMOD, 0xf810, {0x54}, 0x01},
+       {PRO_DMOD, 0xf811, {0x5a}, 0x01},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_60[] = {
+       {PRO_DMOD, 0x0043, {0x00}, 0x01},
+       {PRO_DMOD, 0x0046, {0x60}, 0x01},
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+       {PRO_DMOD, 0x006a, {0x03}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+       {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+       {PRO_DMOD, 0x007e, {0x04}, 0x01},
+       {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+       {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbe, 0xa0, 0xc6, 0xb6, 0x01}, 0x07},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+       {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+       {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+       {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+       {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+       {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+       {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+       {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+       {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+       {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+       {PRO_DMOD, 0x00fc, {    0x03, 0x03, 0x02, 0x0a, 0x50, 0x7b, 0x8c,
+                               0x00, 0x02, 0xbe, 0x00}, 0x0b},
+       {PRO_DMOD, 0x0109, {0x02}, 0x01},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+       {PRO_DMOD, 0x011a, {0xbe}, 0x01},
+       {PRO_DMOD, 0x0124, {0xae}, 0x01},
+       {PRO_DMOD, 0x0127, {0x00}, 0x01},
+       {PRO_DMOD, 0x012a, {0x56, 0x50, 0x47, 0x42}, 0x04},
+       {PRO_DMOD, 0x0137, {0x00}, 0x01},
+       {PRO_DMOD, 0x013b, {0x08}, 0x01},
+       {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+       {PRO_DMOD, 0x0141, {    0x59, 0xf9, 0x19, 0x19, 0x8c, 0x8c, 0x8c,
+                               0x6e, 0x8c, 0x50, 0x8c, 0x8c, 0xac, 0xc6,
+                               0x33}, 0x0f},
+       {PRO_DMOD, 0x0151, {0x28}, 0x01},
+       {PRO_DMOD, 0x0153, {0xbc}, 0x01},
+       {PRO_DMOD, 0x0178, {0x09}, 0x01},
+       {PRO_DMOD, 0x0181, {0x94, 0x6e}, 0x02},
+       {PRO_DMOD, 0x0185, {0x24}, 0x01},
+       {PRO_DMOD, 0x0187, {0x00, 0x00, 0xbe, 0x02, 0x80}, 0x05},
+       {PRO_DMOD, 0xed02, {0xff}, 0x01},
+       {PRO_DMOD, 0xee42, {0xff}, 0x01},
+       {PRO_DMOD, 0xee82, {0xff}, 0x01},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf087, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+       {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+       {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+       {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+       {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+       {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+       {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+       {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+       {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17
+               , 0x1f}, 0x08},
+       {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+       {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_61[] = {
+       {PRO_DMOD, 0x0043, {0x00}, 0x01},
+       {PRO_DMOD, 0x0046, {0x61}, 0x01},
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0x0068, {0x06}, 0x01},
+       {PRO_DMOD, 0x006a, {0x03}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+       {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x90, 0x01}, 0x05},
+       {PRO_DMOD, 0x007e, {0x04}, 0x01},
+       {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+       {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbc, 0x9c, 0xcc, 0xa8, 0x01}, 0x07},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+       {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+       {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+       {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+       {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+       {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+       {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+       {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+       {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+       {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+       {PRO_DMOD, 0x00fc, {    0x03, 0x03, 0x02, 0x08, 0x50, 0x7b, 0x8c,
+                               0x01, 0x02, 0xc8, 0x00}, 0x0b},
+       {PRO_DMOD, 0x0109, {0x02}, 0x01},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+       {PRO_DMOD, 0x011a, {0xc6}, 0x01},
+       {PRO_DMOD, 0x0124, {0xa8}, 0x01},
+       {PRO_DMOD, 0x0127, {0x00}, 0x01},
+       {PRO_DMOD, 0x012a, {0x59, 0x50, 0x47, 0x42}, 0x04},
+       {PRO_DMOD, 0x0137, {0x00}, 0x01},
+       {PRO_DMOD, 0x013b, {0x05}, 0x01},
+       {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+       {PRO_DMOD, 0x0141, {    0x59, 0xf9, 0x59, 0x59, 0x8c, 0x8c, 0x8c,
+                               0x7b, 0x8c, 0x50, 0x8c, 0x8c, 0xa8, 0xc6,
+                               0x33}, 0x0f},
+       {PRO_DMOD, 0x0151, {0x28}, 0x01},
+       {PRO_DMOD, 0x0153, {0xcc}, 0x01},
+       {PRO_DMOD, 0x0178, {0x09}, 0x01},
+       {PRO_DMOD, 0x0181, {0x9c, 0x76}, 0x02},
+       {PRO_DMOD, 0x0185, {0x28}, 0x01},
+       {PRO_DMOD, 0x0187, {0x01, 0x00, 0xaa, 0x02, 0x80}, 0x05},
+       {PRO_DMOD, 0xed02, {0xff}, 0x01},
+       {PRO_DMOD, 0xee42, {0xff}, 0x01},
+       {PRO_DMOD, 0xee82, {0xff}, 0x01},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf087, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+       {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+       {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+       {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+       {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+       {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+       {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+       {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+       {PRO_DMOD, 0xf600, {    0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+                               0x1f}, 0x08},
+       {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+       {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_62[] = {
+       {PRO_DMOD, 0x0043, {0x00}, 0x01},
+       {PRO_DMOD, 0x0046, {0x62}, 0x01},
+       {PRO_DMOD, 0x0051, {0x01}, 0x01},
+       {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+       {PRO_DMOD, 0x006a, {0x03}, 0x01},
+       {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+       {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+       {PRO_DMOD, 0x007e, {0x04}, 0x01},
+       {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+       {PRO_DMOD, 0x0084, {    0x0a, 0x33, 0xb8, 0x9c, 0xb2, 0xa6, 0x01},
+                               0x07},
+       {PRO_DMOD, 0x008e, {0x01}, 0x01},
+       {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+       {PRO_DMOD, 0x0099, {0x01}, 0x01},
+       {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+       {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+       {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+       {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+       {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+       {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+       {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+       {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+       {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+       {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+       {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+       {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+       {PRO_DMOD, 0x00fc, {    0x02, 0x03, 0x02, 0x09, 0x50, 0x6e, 0x8c,
+                               0x02, 0x02, 0xc2, 0x00}, 0x0b},
+       {PRO_DMOD, 0x0109, {0x02}, 0x01},
+       {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+       {PRO_DMOD, 0x011a, {0xb8}, 0x01},
+       {PRO_DMOD, 0x0124, {0xa8}, 0x01},
+       {PRO_DMOD, 0x0127, {0x00}, 0x01},
+       {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+       {PRO_DMOD, 0x0137, {0x00}, 0x01},
+       {PRO_DMOD, 0x013b, {0x05}, 0x01},
+       {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+       {PRO_DMOD, 0x0141, {    0x59, 0xf9, 0x59, 0x19, 0x8c, 0x8c, 0x8c,
+                               0x7b, 0x8c, 0x50, 0x70, 0x8c, 0x96, 0xd0,
+                               0x33}, 0x0f},
+       {PRO_DMOD, 0x0151, {0x28}, 0x01},
+       {PRO_DMOD, 0x0153, {0xb2}, 0x01},
+       {PRO_DMOD, 0x0178, {0x09}, 0x01},
+       {PRO_DMOD, 0x0181, {0x9c, 0x6e}, 0x02},
+       {PRO_DMOD, 0x0185, {0x24}, 0x01},
+       {PRO_DMOD, 0x0187, {0x00, 0x00, 0xb8, 0x02, 0x80}, 0x05},
+       {PRO_DMOD, 0xed02, {0xff}, 0x01},
+       {PRO_DMOD, 0xee42, {0xff}, 0x01},
+       {PRO_DMOD, 0xee82, {0xff}, 0x01},
+       {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+       {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+       {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+       {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+       {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+       {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+       {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+       {PRO_DMOD, 0xf087, {0x00}, 0x01},
+       {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+       {PRO_DMOD, 0xf130, {0x04}, 0x01},
+       {PRO_DMOD, 0xf132, {0x04}, 0x01},
+       {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+       {PRO_DMOD, 0xf146, {0x00}, 0x01},
+       {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+       {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+       {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+       {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+       {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+       {PRO_DMOD, 0xf163, {0x05}, 0x01},
+       {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+       {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+       {PRO_DMOD, 0xf183, {0x01}, 0x01},
+       {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+       {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+       {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+       {PRO_DMOD, 0xf204, {0x10}, 0x01},
+       {PRO_DMOD, 0xf214, {0x00}, 0x01},
+       {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+       {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+       {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+       {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+       {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+       {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+       {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+       {PRO_DMOD, 0xf600, {    0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+                               0x1f}, 0x08},
+       {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+       {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+       {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+       {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+       {PRO_DMOD, 0xf905, {0x01}, 0x01},
+       {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+       {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* Tuner setting scripts (still keeping it9137) */
 static struct it913xset it9137_tuner_off[] = {
        {PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
        {PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
        {PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+       {PRO_DMOD, 0xec06, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00}, 0x0c},
+       {PRO_DMOD, 0xec12, {0x00, 0x00, 0x00, 0x00}, 0x04},
+       {PRO_DMOD, 0xec17, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00}, 0x09},
+       {PRO_DMOD, 0xec22, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00}, 0x0a},
+       {PRO_DMOD, 0xec20, {0x00}, 0x01},
        {PRO_DMOD, 0xec3f, {0x01}, 0x01},
        {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
 };
 
+static struct it913xset set_it9135_template[] = {
+       {PRO_DMOD, 0xee06, {0x00}, 0x01},
+       {PRO_DMOD, 0xec56, {0x00}, 0x01},
+       {PRO_DMOD, 0xec4c, {0x00}, 0x01},
+       {PRO_DMOD, 0xec4d, {0x00}, 0x01},
+       {PRO_DMOD, 0xec4e, {0x00}, 0x01},
+       {PRO_DMOD, 0x011e, {0x00}, 0x01}, /* Older Devices */
+       {PRO_DMOD, 0x011f, {0x00}, 0x01},
+       {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
 static struct it913xset set_it9137_template[] = {
        {PRO_DMOD, 0xee06, {0x00}, 0x01},
        {PRO_DMOD, 0xec56, {0x00}, 0x01},
index d4bd24eb4700d36d612f674cc0793317f0d70ada..ccc36bf2deb403b3a7e769963e0659004d34f75d 100644 (file)
@@ -46,13 +46,17 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
          dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
                *p, *(p+1), *(p+2), *(p+3), *(p+4), \
                        *(p+5), *(p+6), *(p+7));
+#define info(format, arg...) \
+       printk(KERN_INFO "it913x-fe: " format "\n" , ## arg)
 
 struct it913x_fe_state {
        struct dvb_frontend frontend;
        struct i2c_adapter *i2c_adap;
+       struct ite_config *config;
        u8 i2c_addr;
        u32 frequency;
-       u8 adf;
+       fe_modulation_t constellation;
+       fe_transmit_mode_t transmission_mode;
        u32 crystalFrequency;
        u32 adcFrequency;
        u8 tuner_type;
@@ -62,6 +66,7 @@ struct it913x_fe_state {
        u8 tun_fdiv;
        u8 tun_clk_mode;
        u32 tun_fn_min;
+       u32 ucblocks;
 };
 
 static int it913x_read_reg(struct it913x_fe_state *state,
@@ -211,20 +216,24 @@ static int it913x_init_tuner(struct it913x_fe_state *state)
        state->tun_fn_min /= (state->tun_fdiv * nv_val);
        deb_info("Tuner fn_min %d", state->tun_fn_min);
 
-       for (i = 0; i < 50; i++) {
-               reg = it913x_read_reg_u8(state, 0xec82);
-               if (reg > 0)
-                       break;
-               if (reg < 0)
-                       return -ENODEV;
-               udelay(2000);
+       if (state->config->chip_ver > 1)
+               msleep(50);
+       else {
+               for (i = 0; i < 50; i++) {
+                       reg = it913x_read_reg_u8(state, 0xec82);
+                       if (reg > 0)
+                               break;
+                       if (reg < 0)
+                               return -ENODEV;
+                       udelay(2000);
+               }
        }
 
        return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
 }
 
 static int it9137_set_tuner(struct it913x_fe_state *state,
-               enum fe_bandwidth bandwidth, u32 frequency_m)
+               u32 bandwidth, u32 frequency_m)
 {
        struct it913xset *set_tuner = set_it9137_template;
        int ret, reg;
@@ -237,6 +246,11 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
        u8 lna_band;
        u8 bw;
 
+       if (state->config->firmware_ver == 1)
+               set_tuner = set_it9135_template;
+       else
+               set_tuner = set_it9137_template;
+
        deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
 
        if (frequency >= 51000 && frequency <= 440000) {
@@ -273,16 +287,21 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
                return -EINVAL;
        set_tuner[0].reg[0] = lna_band;
 
-       if (bandwidth == BANDWIDTH_5_MHZ)
+       switch (bandwidth) {
+       case 5000000:
                bw = 0;
-       else if (bandwidth == BANDWIDTH_6_MHZ)
+               break;
+       case 6000000:
                bw = 2;
-       else if (bandwidth == BANDWIDTH_7_MHZ)
+               break;
+       case 7000000:
                bw = 4;
-       else if (bandwidth == BANDWIDTH_8_MHZ)
-               bw = 6;
-       else
+               break;
+       default:
+       case 8000000:
                bw = 6;
+               break;
+       }
 
        set_tuner[1].reg[0] = bw;
        set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
@@ -361,7 +380,7 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
 }
 
 static int it913x_fe_select_bw(struct it913x_fe_state *state,
-                       enum fe_bandwidth bandwidth, u32 adcFrequency)
+                       u32 bandwidth, u32 adcFrequency)
 {
        int ret, i;
        u8 buffer[256];
@@ -374,17 +393,21 @@ static int it913x_fe_select_bw(struct it913x_fe_state *state,
 
        deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
 
-       if (bandwidth == BANDWIDTH_5_MHZ)
+       switch (bandwidth) {
+       case 5000000:
                bw = 3;
-       else if (bandwidth == BANDWIDTH_6_MHZ)
+               break;
+       case 6000000:
                bw = 0;
-       else if (bandwidth == BANDWIDTH_7_MHZ)
+               break;
+       case 7000000:
                bw = 1;
-       else if (bandwidth == BANDWIDTH_8_MHZ)
-               bw = 2;
-       else
+               break;
+       default:
+       case 8000000:
                bw = 2;
-
+               break;
+       }
        ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
 
        if (state->table == NULL)
@@ -492,31 +515,79 @@ static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
        return 0;
 }
 
-static int it913x_fe_read_snr(struct dvb_frontend *fe, u16snr)
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct it913x_fe_state *state = fe->demodulator_priv;
-       int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
-       ret = (ret * 0xff) / 0x64;
-       ret |= (ret << 0x8);
-       *snr = ~ret;
-       return 0;
+       int ret;
+       u8 reg[3];
+       u32 snr_val, snr_min, snr_max;
+       u32 temp;
+
+       ret = it913x_read_reg(state, 0x2c, reg, sizeof(reg));
+
+       snr_val = (u32)(reg[2] << 16) | (reg[1] << 8) | reg[0];
+
+       ret |= it913x_read_reg(state, 0xf78b, reg, 1);
+       if (reg[0])
+               snr_val /= reg[0];
+
+       if (state->transmission_mode == TRANSMISSION_MODE_2K)
+               snr_val *= 4;
+       else if (state->transmission_mode == TRANSMISSION_MODE_4K)
+               snr_val *= 2;
+
+       if (state->constellation == QPSK) {
+               snr_min = 0xb4711;
+               snr_max = 0x191451;
+       } else if (state->constellation == QAM_16) {
+               snr_min = 0x4f0d5;
+               snr_max = 0xc7925;
+       } else if (state->constellation == QAM_64) {
+               snr_min = 0x256d0;
+               snr_max = 0x626be;
+       } else
+               return -EINVAL;
+
+       if (snr_val < snr_min)
+               *snr = 0;
+       else if (snr_val < snr_max) {
+               temp = (snr_val - snr_min) >> 5;
+               temp *= 0xffff;
+               temp /= (snr_max - snr_min) >> 5;
+               *snr = (u16)temp;
+       } else
+               *snr = 0xffff;
+
+       return (ret < 0) ? -ENODEV : 0;
 }
 
 static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-       *ber = 0;
+       struct it913x_fe_state *state = fe->demodulator_priv;
+       int ret;
+       u8 reg[5];
+       /* Read Aborted Packets and Pre-Viterbi error rate 5 bytes */
+       ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+       state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+       *ber = (u32)(reg[4] << 16) | (reg[3] << 8) | reg[2];
        return 0;
 }
 
 static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
-       *ucblocks = 0;
-       return 0;
+       struct it913x_fe_state *state = fe->demodulator_priv;
+       int ret;
+       u8 reg[2];
+       /* Aborted Packets */
+       ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+       state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+       *ucblocks = state->ucblocks;
+       return ret;
 }
 
-static int it913x_fe_get_frontend(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *p)
+static int it913x_fe_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct it913x_fe_state *state = fe->demodulator_priv;
        int ret;
        u8 reg[8];
@@ -524,26 +595,30 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe,
        ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
 
        if (reg[3] < 3)
-               p->u.ofdm.constellation = fe_con[reg[3]];
+               p->modulation = fe_con[reg[3]];
 
        if (reg[0] < 3)
-               p->u.ofdm.transmission_mode = fe_mode[reg[0]];
+               p->transmission_mode = fe_mode[reg[0]];
 
        if (reg[1] < 4)
-               p->u.ofdm.guard_interval = fe_gi[reg[1]];
+               p->guard_interval = fe_gi[reg[1]];
 
        if (reg[2] < 4)
-               p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
+               p->hierarchy = fe_hi[reg[2]];
+
+       p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+       p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
 
-       p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
-       p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+       /* Update internal state to reflect the autodetected props */
+       state->constellation = p->modulation;
+       state->transmission_mode = p->transmission_mode;
 
        return 0;
 }
 
-static int it913x_fe_set_frontend(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *p)
+static int it913x_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct it913x_fe_state *state = fe->demodulator_priv;
        int ret, i;
        u8 empty_ch, last_ch;
@@ -551,7 +626,7 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe,
        state->it913x_status = 0;
 
        /* Set bw*/
-       ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
+       ret = it913x_fe_select_bw(state, p->bandwidth_hz,
                state->adcFrequency);
 
        /* Training Mode Off */
@@ -571,20 +646,25 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe,
                        i = 1;
        else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
                        i = 2;
-               else
-                       return -EOPNOTSUPP;
+       else
+               return -EOPNOTSUPP;
 
        ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
 
        deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
        switch (state->tuner_type) {
-       case IT9137: /* Tuner type 0x38 */
+       case IT9135_38:
+       case IT9135_51:
+       case IT9135_52:
+       case IT9135_60:
+       case IT9135_61:
+       case IT9135_62:
                ret = it9137_set_tuner(state,
-                       p->u.ofdm.bandwidth, p->frequency);
+                       p->bandwidth_hz, p->frequency);
                break;
        default:
                if (fe->ops.tuner_ops.set_params) {
-                       fe->ops.tuner_ops.set_params(fe, p);
+                       fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl)
                                fe->ops.i2c_gate_ctrl(fe, 0);
                }
@@ -678,16 +758,19 @@ static u32 compute_div(u32 a, u32 b, u32 x)
 
 static int it913x_fe_start(struct it913x_fe_state *state)
 {
-       struct it913xset *set_fe;
+       struct it913xset *set_lna;
        struct it913xset *set_mode;
        int ret;
-       u8 adf = (state->adf & 0xf);
+       u8 adf = (state->config->adf & 0xf);
        u32 adc, xtal;
        u8 b[4];
 
-       ret = it913x_init_tuner(state);
+       if (state->config->chip_ver == 1)
+               ret = it913x_init_tuner(state);
+
+       info("ADF table value   :%02x", adf);
 
-       if (adf < 12) {
+       if (adf < 10) {
                state->crystalFrequency = fe_clockTable[adf].xtal ;
                state->table = fe_clockTable[adf].table;
                state->adcFrequency = state->table->adcFrequency;
@@ -698,9 +781,6 @@ static int it913x_fe_start(struct it913x_fe_state *state)
        } else
                return -EINVAL;
 
-       deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
-               state->crystalFrequency, state->adcFrequency, adc, xtal);
-
        /* Set LED indicator on GPIOH3 */
        ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
        ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
@@ -721,22 +801,71 @@ static int it913x_fe_start(struct it913x_fe_state *state)
        b[2] = (adc >> 16) & 0xff;
        ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
 
+       if (state->config->adc_x2)
+               ret |= it913x_write_reg(state, PRO_DMOD, ADC_X_2, 0x01);
+       b[0] = 0;
+       b[1] = 0;
+       b[2] = 0;
+       ret |= it913x_write(state, PRO_DMOD, 0x0029, b, 3);
+
+       info("Crystal Frequency :%d Adc Frequency :%d ADC X2: %02x",
+               state->crystalFrequency, state->adcFrequency,
+                       state->config->adc_x2);
+       deb_info("Xtal value :%04x Adc value :%04x", xtal, adc);
+
+       if (ret < 0)
+               return -ENODEV;
+
+       /* v1 or v2 tuner script */
+       if (state->config->chip_ver > 1)
+               ret = it913x_fe_script_loader(state, it9135_v2);
+       else
+               ret = it913x_fe_script_loader(state, it9135_v1);
+       if (ret < 0)
+               return ret;
+
+       /* LNA Scripts */
        switch (state->tuner_type) {
-       case IT9137: /* Tuner type 0x38 */
-               set_fe = it9137_set;
+       case IT9135_51:
+               set_lna = it9135_51;
+               break;
+       case IT9135_52:
+               set_lna = it9135_52;
+               break;
+       case IT9135_60:
+               set_lna = it9135_60;
+               break;
+       case IT9135_61:
+               set_lna = it9135_61;
                break;
+       case IT9135_62:
+               set_lna = it9135_62;
+               break;
+       case IT9135_38:
        default:
-               return -EINVAL;
+               set_lna = it9135_38;
        }
+       info("Tuner LNA type :%02x", state->tuner_type);
+
+       ret = it913x_fe_script_loader(state, set_lna);
+       if (ret < 0)
+               return ret;
+
+       if (state->config->chip_ver == 2) {
+               ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x1);
+               ret |= it913x_write_reg(state, PRO_LINK, PADODPU, 0x0);
+               ret |= it913x_write_reg(state, PRO_LINK, AGC_O_D, 0x0);
+               ret |= it913x_init_tuner(state);
+       }
+       if (ret < 0)
+               return -ENODEV;
 
-       /* set the demod */
-       ret = it913x_fe_script_loader(state, set_fe);
        /* Always solo frontend */
        set_mode = set_solo_fe;
        ret |= it913x_fe_script_loader(state, set_mode);
 
        ret |= it913x_fe_suspend(state);
-       return 0;
+       return (ret < 0) ? -ENODEV : 0;
 }
 
 static int it913x_fe_init(struct dvb_frontend *fe)
@@ -746,17 +875,11 @@ static int it913x_fe_init(struct dvb_frontend *fe)
        /* Power Up Tuner - common all versions */
        ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
 
-       ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
-
        ret |= it913x_fe_script_loader(state, init_1);
 
-       switch (state->tuner_type) {
-       case IT9137:
-               ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
-               break;
-       default:
-               return -EINVAL;
-       }
+       ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+       ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
 
        return (ret < 0) ? -ENODEV : 0;
 }
@@ -770,19 +893,34 @@ static void it913x_fe_release(struct dvb_frontend *fe)
 static struct dvb_frontend_ops it913x_fe_ofdm_ops;
 
 struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
-               u8 i2c_addr, u8 adf, u8 type)
+               u8 i2c_addr, struct ite_config *config)
 {
        struct it913x_fe_state *state = NULL;
        int ret;
+
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
        if (state == NULL)
+               return NULL;
+       if (config == NULL)
                goto error;
 
        state->i2c_adap = i2c_adap;
        state->i2c_addr = i2c_addr;
-       state->adf = adf;
-       state->tuner_type = type;
+       state->config = config;
+
+       switch (state->config->tuner_id_0) {
+       case IT9135_51:
+       case IT9135_52:
+       case IT9135_60:
+       case IT9135_61:
+       case IT9135_62:
+               state->tuner_type = state->config->tuner_id_0;
+               break;
+       default:
+       case IT9135_38:
+               state->tuner_type = IT9135_38;
+       }
 
        ret = it913x_fe_start(state);
        if (ret < 0)
@@ -802,10 +940,9 @@ error:
 EXPORT_SYMBOL(it913x_fe_attach);
 
 static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "it913x-fe DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 51000000,
                .frequency_max          = 1680000000,
                .frequency_stepsize     = 62500,
@@ -835,5 +972,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
 
 MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
 MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_VERSION("1.07");
+MODULE_VERSION("1.13");
 MODULE_LICENSE("GPL");
index 9d97f32e690b4261ea5980b2b964b2f499eaeb42..c4a908e354e0d3528a4ca94d17a9865e6356fc76 100644 (file)
 
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
+
+struct ite_config {
+       u8 chip_ver;
+       u16 chip_type;
+       u32 firmware;
+       u8 firmware_ver;
+       u8 adc_x2;
+       u8 tuner_id_0;
+       u8 tuner_id_1;
+       u8 dual_mode;
+       u8 adf;
+};
+
 #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
 defined(MODULE))
 extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
-                       u8 i2c_addr, u8 adf, u8 type);
+                       u8 i2c_addr, struct ite_config *config);
 #else
 static inline struct dvb_frontend *it913x_fe_attach(
-               struct i2c_adapter *i2c_adap,   u8 i2c_addr, u8 adf, u8 type)
+               struct i2c_adapter *i2c_adap,
+                       u8 i2c_addr, struct ite_config *config)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
@@ -134,6 +148,16 @@ static inline struct dvb_frontend *it913x_fe_attach(
 #define COEFF_1_2048           0x0001
 #define XTAL_CLK               0x0025
 #define BFS_FCW                        0x0029
+
+/* Error Regs */
+#define RSD_ABORT_PKT_LSB      0x0032
+#define RSD_ABORT_PKT_MSB      0x0033
+#define RSD_BIT_ERR_0_7                0x0034
+#define RSD_BIT_ERR_8_15       0x0035
+#define RSD_BIT_ERR_23_16      0x0036
+#define RSD_BIT_COUNT_LSB      0x0037
+#define RSD_BIT_COUNT_MSB      0x0038
+
 #define TPSD_LOCK              0x003c
 #define TRAINING_MODE          0x0040
 #define ADC_X_2                        0x0045
@@ -144,8 +168,14 @@ static inline struct dvb_frontend *it913x_fe_attach(
 #define EST_SIGNAL_LEVEL       0x004a
 #define FREE_BAND              0x004b
 #define SUSPEND_FLAG           0x004c
-/* Build in tuners */
+/* Build in tuner types */
 #define IT9137 0x38
+#define IT9135_38 0x38
+#define IT9135_51 0x51
+#define IT9135_52 0x52
+#define IT9135_60 0x60
+#define IT9135_61 0x61
+#define IT9135_62 0x62
 
 enum {
        CMD_DEMOD_READ = 0,
@@ -193,4 +223,11 @@ enum {
        WRITE_CMD,
 };
 
+enum {
+       IT9135_AUTO = 0,
+       IT9137_FW,
+       IT9135_V1_FW,
+       IT9135_V2_FW,
+};
+
 #endif /* IT913X_FE_H */
index aa9ccb821fa51fe9a6f8612c5cbb491f065f7c2f..316457584fe7a6fe7a18ae430fe1c194393dbf7c 100644 (file)
@@ -250,13 +250,14 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
        itd1000_set_vco(state, freq_khz);
 }
 
-static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int itd1000_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        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);
+       itd1000_set_lo(state, c->frequency);
+       itd1000_set_lpf_bw(state, c->symbol_rate);
 
        pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
        itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
index 9a517a4bf96dea9a61611ead392713bedf0d637c..bc5a82082aaae7891d55dd2cd3c6eabff93e9b84 100644 (file)
@@ -129,12 +129,12 @@ static int ix2505v_release(struct dvb_frontend *fe)
  *  1 -> 8 -> 6
  */
 
-static int ix2505v_set_params(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *params)
+static int ix2505v_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct ix2505v_state *state = fe->tuner_priv;
-       u32 frequency = params->frequency;
-       u32 b_w  = (params->u.qpsk.symbol_rate * 27) / 32000;
+       u32 frequency = c->frequency;
+       u32 b_w  = (c->symbol_rate * 27) / 32000;
        u32 div_factor, N , A, x;
        int ret = 0, len;
        u8 gain, cc, ref, psc, local_osc, lpf;
index 445fa10680644c9d546d5aa8644947e6b5587573..36fcf559e3619147da5dde357aba6267213357fa 100644 (file)
@@ -117,18 +117,17 @@ static int reset_and_configure (struct l64781_state* state)
        return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
 }
 
-static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
+static int apply_frontend_param(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct l64781_state* state = fe->demodulator_priv;
        /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
        static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
        /* QPSK, QAM_16, QAM_64 */
        static const u8 qam_tab [] = { 2, 4, 0, 6 };
-       static const u8 bw_tab [] = { 8, 7, 6 };  /* 8Mhz, 7MHz, 6MHz */
        static const u8 guard_tab [] = { 1, 2, 4, 8 };
        /* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
        static const u32 ppm = 8000;
-       struct dvb_ofdm_parameters *p = &param->u.ofdm;
        u32 ddfs_offset_fixed;
 /*     u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
 /*                     bw_tab[p->bandWidth]<<10)/15625; */
@@ -137,18 +136,29 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
        u8 val0x04;
        u8 val0x05;
        u8 val0x06;
-       int bw = p->bandwidth - BANDWIDTH_8_MHZ;
+       int bw;
+
+       switch (p->bandwidth_hz) {
+       case 8000000:
+               bw = 8;
+               break;
+       case 7000000:
+               bw = 7;
+               break;
+       case 6000000:
+               bw = 6;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       if (param->inversion != INVERSION_ON &&
-           param->inversion != INVERSION_OFF)
-               return -EINVAL;
-
-       if (bw < 0 || bw > 2)
+       if (p->inversion != INVERSION_ON &&
+           p->inversion != INVERSION_OFF)
                return -EINVAL;
 
        if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
@@ -156,14 +166,14 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
            p->code_rate_HP != FEC_7_8)
                return -EINVAL;
 
-       if (p->hierarchy_information != HIERARCHY_NONE &&
+       if (p->hierarchy != HIERARCHY_NONE &&
            (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
             p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
             p->code_rate_LP != FEC_7_8))
                return -EINVAL;
 
-       if (p->constellation != QPSK && p->constellation != QAM_16 &&
-           p->constellation != QAM_64)
+       if (p->modulation != QPSK && p->modulation != QAM_16 &&
+           p->modulation != QAM_64)
                return -EINVAL;
 
        if (p->transmission_mode != TRANSMISSION_MODE_2K &&
@@ -174,22 +184,22 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
            p->guard_interval > GUARD_INTERVAL_1_4)
                return -EINVAL;
 
-       if (p->hierarchy_information < HIERARCHY_NONE ||
-           p->hierarchy_information > HIERARCHY_4)
+       if (p->hierarchy < HIERARCHY_NONE ||
+           p->hierarchy > HIERARCHY_4)
                return -EINVAL;
 
-       ddfs_offset_fixed = 0x4000-(ppm<<16)/bw_tab[p->bandwidth]/1000000;
+       ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
 
        /* This works up to 20000 ppm, it overflows if too large ppm! */
        init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
-                       bw_tab[p->bandwidth] & 0xFFFFFF);
+                       bw & 0xFFFFFF);
 
        /* SPI bias calculation is slightly modified to fit in 32bit */
        /* will work for high ppm only... */
        spi_bias = 378 * (1 << 10);
        spi_bias *= 16;
-       spi_bias *= bw_tab[p->bandwidth];
-       spi_bias *= qam_tab[p->constellation];
+       spi_bias *= bw;
+       spi_bias *= qam_tab[p->modulation];
        spi_bias /= p->code_rate_HP + 1;
        spi_bias /= (guard_tab[p->guard_interval] + 32);
        spi_bias *= 1000;
@@ -199,10 +209,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
        val0x04 = (p->transmission_mode << 2) | p->guard_interval;
        val0x05 = fec_tab[p->code_rate_HP];
 
-       if (p->hierarchy_information != HIERARCHY_NONE)
+       if (p->hierarchy != HIERARCHY_NONE)
                val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
 
-       val0x06 = (p->hierarchy_information << 2) | p->constellation;
+       val0x06 = (p->hierarchy << 2) | p->modulation;
 
        l64781_writereg (state, 0x04, val0x04);
        l64781_writereg (state, 0x05, val0x05);
@@ -220,7 +230,7 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
        l64781_writereg (state, 0x1b, spi_bias & 0xff);
        l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
        l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
-               (param->inversion == INVERSION_ON ? 0x80 : 0x00));
+               (p->inversion == INVERSION_ON ? 0x80 : 0x00));
 
        l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
        l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
@@ -233,8 +243,9 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
        return 0;
 }
 
-static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* param)
+static int get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct l64781_state* state = fe->demodulator_priv;
        int tmp;
 
@@ -242,98 +253,95 @@ static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters*
        tmp = l64781_readreg(state, 0x04);
        switch(tmp & 3) {
        case 0:
-               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               p->guard_interval = GUARD_INTERVAL_1_32;
                break;
        case 1:
-               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               p->guard_interval = GUARD_INTERVAL_1_16;
                break;
        case 2:
-               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               p->guard_interval = GUARD_INTERVAL_1_8;
                break;
        case 3:
-               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               p->guard_interval = GUARD_INTERVAL_1_4;
                break;
        }
        switch((tmp >> 2) & 3) {
        case 0:
-               param->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               p->transmission_mode = TRANSMISSION_MODE_2K;
                break;
        case 1:
-               param->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               p->transmission_mode = TRANSMISSION_MODE_8K;
                break;
        default:
-               printk("Unexpected value for transmission_mode\n");
+               printk(KERN_WARNING "Unexpected value for transmission_mode\n");
        }
 
-
-
        tmp = l64781_readreg(state, 0x05);
        switch(tmp & 7) {
        case 0:
-               param->u.ofdm.code_rate_HP = FEC_1_2;
+               p->code_rate_HP = FEC_1_2;
                break;
        case 1:
-               param->u.ofdm.code_rate_HP = FEC_2_3;
+               p->code_rate_HP = FEC_2_3;
                break;
        case 2:
-               param->u.ofdm.code_rate_HP = FEC_3_4;
+               p->code_rate_HP = FEC_3_4;
                break;
        case 3:
-               param->u.ofdm.code_rate_HP = FEC_5_6;
+               p->code_rate_HP = FEC_5_6;
                break;
        case 4:
-               param->u.ofdm.code_rate_HP = FEC_7_8;
+               p->code_rate_HP = FEC_7_8;
                break;
        default:
                printk("Unexpected value for code_rate_HP\n");
        }
        switch((tmp >> 3) & 7) {
        case 0:
-               param->u.ofdm.code_rate_LP = FEC_1_2;
+               p->code_rate_LP = FEC_1_2;
                break;
        case 1:
-               param->u.ofdm.code_rate_LP = FEC_2_3;
+               p->code_rate_LP = FEC_2_3;
                break;
        case 2:
-               param->u.ofdm.code_rate_LP = FEC_3_4;
+               p->code_rate_LP = FEC_3_4;
                break;
        case 3:
-               param->u.ofdm.code_rate_LP = FEC_5_6;
+               p->code_rate_LP = FEC_5_6;
                break;
        case 4:
-               param->u.ofdm.code_rate_LP = FEC_7_8;
+               p->code_rate_LP = FEC_7_8;
                break;
        default:
                printk("Unexpected value for code_rate_LP\n");
        }
 
-
        tmp = l64781_readreg(state, 0x06);
        switch(tmp & 3) {
        case 0:
-               param->u.ofdm.constellation = QPSK;
+               p->modulation = QPSK;
                break;
        case 1:
-               param->u.ofdm.constellation = QAM_16;
+               p->modulation = QAM_16;
                break;
        case 2:
-               param->u.ofdm.constellation = QAM_64;
+               p->modulation = QAM_64;
                break;
        default:
-               printk("Unexpected value for constellation\n");
+               printk(KERN_WARNING "Unexpected value for modulation\n");
        }
        switch((tmp >> 2) & 7) {
        case 0:
-               param->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               p->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               param->u.ofdm.hierarchy_information = HIERARCHY_1;
+               p->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               param->u.ofdm.hierarchy_information = HIERARCHY_2;
+               p->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               param->u.ofdm.hierarchy_information = HIERARCHY_4;
+               p->hierarchy = HIERARCHY_4;
                break;
        default:
                printk("Unexpected value for hierarchy\n");
@@ -341,12 +349,12 @@ static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters*
 
 
        tmp = l64781_readreg (state, 0x1d);
-       param->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
+       p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
 
        tmp = (int) (l64781_readreg (state, 0x08) |
                     (l64781_readreg (state, 0x09) << 8) |
                     (l64781_readreg (state, 0x0a) << 16));
-       param->frequency += tmp;
+       p->frequency += tmp;
 
        return 0;
 }
@@ -564,10 +572,9 @@ error:
 }
 
 static struct dvb_frontend_ops l64781_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "LSI L64781 DVB-T",
-               .type = FE_OFDM,
        /*      .frequency_min = ???,*/
        /*      .frequency_max = ???,*/
                .frequency_stepsize = 166666,
index 3272881cb112922e30d829c010b9fde5fc3fe4f4..1d2c47378cf856b392534dd2b4599de7d3ac344f 100644 (file)
@@ -266,7 +266,7 @@ fail:
 }
 
 static int lgdt3305_set_modulation(struct lgdt3305_state *state,
-                                  struct dvb_frontend_parameters *param)
+                                  struct dtv_frontend_properties *p)
 {
        u8 opermode;
        int ret;
@@ -279,7 +279,7 @@ static int lgdt3305_set_modulation(struct lgdt3305_state *state,
 
        opermode &= ~0x03;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                opermode |= 0x03;
                break;
@@ -298,11 +298,11 @@ fail:
 }
 
 static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
-                                        struct dvb_frontend_parameters *param)
+                                        struct dtv_frontend_properties *p)
 {
        int val;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                val = 0;
                break;
@@ -321,11 +321,11 @@ static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
 /* ------------------------------------------------------------------------ */
 
 static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
-                                        struct dvb_frontend_parameters *param)
+                                        struct dtv_frontend_properties *p)
 {
        u16 agc_ref;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                agc_ref = 0x32c4;
                break;
@@ -348,11 +348,11 @@ static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
 }
 
 static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
-                              struct dvb_frontend_parameters *param)
+                              struct dtv_frontend_properties *p)
 {
        u16 ifbw, rfbw, agcdelay;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                agcdelay = 0x04c0;
                rfbw     = 0x8000;
@@ -398,11 +398,11 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
 }
 
 static int lgdt3305_agc_setup(struct lgdt3305_state *state,
-                             struct dvb_frontend_parameters *param)
+                             struct dtv_frontend_properties *p)
 {
        int lockdten, acqen;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                lockdten = 0;
                acqen = 0;
@@ -432,15 +432,15 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
                return -EINVAL;
        }
 
-       return lgdt3305_rfagc_loop(state, param);
+       return lgdt3305_rfagc_loop(state, p);
 }
 
 static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
-                                     struct dvb_frontend_parameters *param)
+                                     struct dtv_frontend_properties *p)
 {
        u16 usref = 0;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                if (state->cfg->usref_8vsb)
                        usref = state->cfg->usref_8vsb;
@@ -473,14 +473,14 @@ static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
 /* ------------------------------------------------------------------------ */
 
 static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
-                                      struct dvb_frontend_parameters *param,
+                                      struct dtv_frontend_properties *p,
                                       int inversion)
 {
        int ret;
 
        lg_dbg("(%d)\n", inversion);
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
                                         inversion ? 0xf9 : 0x79);
@@ -497,13 +497,13 @@ static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
 }
 
 static int lgdt3305_set_if(struct lgdt3305_state *state,
-                          struct dvb_frontend_parameters *param)
+                          struct dtv_frontend_properties *p)
 {
        u16 if_freq_khz;
        u8 nco1, nco2, nco3, nco4;
        u64 nco;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                if_freq_khz = state->cfg->vsb_if_khz;
                break;
@@ -517,7 +517,7 @@ static int lgdt3305_set_if(struct lgdt3305_state *state,
 
        nco = if_freq_khz / 10;
 
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                nco <<= 24;
                do_div(nco, 625);
@@ -677,37 +677,37 @@ fail:
        return ret;
 }
 
-static int lgdt3304_set_parameters(struct dvb_frontend *fe,
-                                  struct dvb_frontend_parameters *param)
+static int lgdt3304_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgdt3305_state *state = fe->demodulator_priv;
        int ret;
 
-       lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+       lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
 
        if (fe->ops.tuner_ops.set_params) {
-               ret = fe->ops.tuner_ops.set_params(fe, param);
+               ret = fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
                if (lg_fail(ret))
                        goto fail;
-               state->current_frequency = param->frequency;
+               state->current_frequency = p->frequency;
        }
 
-       ret = lgdt3305_set_modulation(state, param);
+       ret = lgdt3305_set_modulation(state, p);
        if (lg_fail(ret))
                goto fail;
 
-       ret = lgdt3305_passband_digital_agc(state, param);
+       ret = lgdt3305_passband_digital_agc(state, p);
        if (lg_fail(ret))
                goto fail;
 
-       ret = lgdt3305_agc_setup(state, param);
+       ret = lgdt3305_agc_setup(state, p);
        if (lg_fail(ret))
                goto fail;
 
        /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
-       switch (param->u.vsb.modulation) {
+       switch (p->modulation) {
        case VSB_8:
                lgdt3305_write_reg(state, 0x030d, 0x00);
                lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
@@ -718,7 +718,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe,
        case QAM_64:
        case QAM_256:
                lgdt3305_write_reg(state, 0x030d, 0x14);
-               ret = lgdt3305_set_if(state, param);
+               ret = lgdt3305_set_if(state, p);
                if (lg_fail(ret))
                        goto fail;
                break;
@@ -727,13 +727,13 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe,
        }
 
 
-       ret = lgdt3305_spectral_inversion(state, param,
+       ret = lgdt3305_spectral_inversion(state, p,
                                          state->cfg->spectral_inversion
                                          ? 1 : 0);
        if (lg_fail(ret))
                goto fail;
 
-       state->current_modulation = param->u.vsb.modulation;
+       state->current_modulation = p->modulation;
 
        ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
        if (lg_fail(ret))
@@ -747,34 +747,34 @@ fail:
        return ret;
 }
 
-static int lgdt3305_set_parameters(struct dvb_frontend *fe,
-                                  struct dvb_frontend_parameters *param)
+static int lgdt3305_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgdt3305_state *state = fe->demodulator_priv;
        int ret;
 
-       lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+       lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
 
        if (fe->ops.tuner_ops.set_params) {
-               ret = fe->ops.tuner_ops.set_params(fe, param);
+               ret = fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
                if (lg_fail(ret))
                        goto fail;
-               state->current_frequency = param->frequency;
+               state->current_frequency = p->frequency;
        }
 
-       ret = lgdt3305_set_modulation(state, param);
+       ret = lgdt3305_set_modulation(state, p);
        if (lg_fail(ret))
                goto fail;
 
-       ret = lgdt3305_passband_digital_agc(state, param);
+       ret = lgdt3305_passband_digital_agc(state, p);
        if (lg_fail(ret))
                goto fail;
-       ret = lgdt3305_set_agc_power_ref(state, param);
+       ret = lgdt3305_set_agc_power_ref(state, p);
        if (lg_fail(ret))
                goto fail;
-       ret = lgdt3305_agc_setup(state, param);
+       ret = lgdt3305_agc_setup(state, p);
        if (lg_fail(ret))
                goto fail;
 
@@ -786,20 +786,20 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe,
        if (lg_fail(ret))
                goto fail;
 
-       ret = lgdt3305_set_if(state, param);
+       ret = lgdt3305_set_if(state, p);
        if (lg_fail(ret))
                goto fail;
-       ret = lgdt3305_spectral_inversion(state, param,
+       ret = lgdt3305_spectral_inversion(state, p,
                                          state->cfg->spectral_inversion
                                          ? 1 : 0);
        if (lg_fail(ret))
                goto fail;
 
-       ret = lgdt3305_set_filter_extension(state, param);
+       ret = lgdt3305_set_filter_extension(state, p);
        if (lg_fail(ret))
                goto fail;
 
-       state->current_modulation = param->u.vsb.modulation;
+       state->current_modulation = p->modulation;
 
        ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
        if (lg_fail(ret))
@@ -813,15 +813,15 @@ fail:
        return ret;
 }
 
-static int lgdt3305_get_frontend(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *param)
+static int lgdt3305_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgdt3305_state *state = fe->demodulator_priv;
 
        lg_dbg("\n");
 
-       param->u.vsb.modulation = state->current_modulation;
-       param->frequency = state->current_frequency;
+       p->modulation = state->current_modulation;
+       p->frequency = state->current_frequency;
        return 0;
 }
 
@@ -1166,9 +1166,9 @@ fail:
 EXPORT_SYMBOL(lgdt3305_attach);
 
 static struct dvb_frontend_ops lgdt3304_ops = {
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name = "LG Electronics LGDT3304 VSB/QAM Frontend",
-               .type               = FE_ATSC,
                .frequency_min      = 54000000,
                .frequency_max      = 858000000,
                .frequency_stepsize = 62500,
@@ -1188,9 +1188,9 @@ static struct dvb_frontend_ops lgdt3304_ops = {
 };
 
 static struct dvb_frontend_ops lgdt3305_ops = {
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name = "LG Electronics LGDT3305 VSB/QAM Frontend",
-               .type               = FE_ATSC,
                .frequency_min      = 54000000,
                .frequency_max      = 858000000,
                .frequency_stepsize = 62500,
index 43971e63baa727c5a3c7de9cbc05dc4c8fc4207e..c990d35a13dcdf2617d7efb65d7ea782735b9939 100644 (file)
@@ -288,6 +288,8 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        int err;
        u8 buf[2];
 
+       *ucblocks = 0;
+
        switch (state->config->demod_chip) {
        case LGDT3302:
                err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
@@ -302,14 +304,16 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
                       "Only LGDT3302 and LGDT3303 are supported chips.\n");
                err = -ENODEV;
        }
+       if (err < 0)
+               return err;
 
        *ucblocks = (buf[0] << 8) | buf[1];
        return 0;
 }
 
-static int lgdt330x_set_parameters(struct dvb_frontend* fe,
-                                  struct dvb_frontend_parameters *param)
+static int lgdt330x_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        /*
         * Array of byte pairs <address, value>
         * to initialize 8VSB for lgdt3303 chip 50 MHz IF
@@ -343,10 +347,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
 
        static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
 
-       int err;
+       int err = 0;
        /* Change only if we are actually changing the modulation */
-       if (state->current_modulation != param->u.vsb.modulation) {
-               switch(param->u.vsb.modulation) {
+       if (state->current_modulation != p->modulation) {
+               switch (p->modulation) {
                case VSB_8:
                        dprintk("%s: VSB_8 MODE\n", __func__);
 
@@ -395,9 +399,14 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        }
                        break;
                default:
-                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
+                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, p->modulation);
                        return -1;
                }
+               if (err < 0)
+                       printk(KERN_WARNING "lgdt330x: %s: error blasting "
+                              "bytes to lgdt3303 for modulation type(%d)\n",
+                              __func__, p->modulation);
+
                /*
                 * select serial or parallel MPEG harware interface
                 * Serial:   0x04 for LGDT3302 or 0x40 for LGDT3303
@@ -410,29 +419,29 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                                      sizeof(top_ctrl_cfg));
                if (state->config->set_ts_params)
                        state->config->set_ts_params(fe, 0);
-               state->current_modulation = param->u.vsb.modulation;
+               state->current_modulation = p->modulation;
        }
 
        /* Tune to the specified frequency */
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        /* Keep track of the new frequency */
        /* FIXME this is the wrong way to do this...           */
        /* The tuner is shared with the video4linux analog API */
-       state->current_frequency = param->frequency;
+       state->current_frequency = p->frequency;
 
        lgdt330x_SwReset(state);
        return 0;
 }
 
-static int lgdt330x_get_frontend(struct dvb_frontend* fe,
-                                struct dvb_frontend_parameters* param)
+static int lgdt330x_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgdt330x_state *state = fe->demodulator_priv;
-       param->frequency = state->current_frequency;
+       p->frequency = state->current_frequency;
        return 0;
 }
 
@@ -762,9 +771,9 @@ error:
 }
 
 static struct dvb_frontend_ops lgdt3302_ops = {
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
-               .type = FE_ATSC,
                .frequency_min= 54000000,
                .frequency_max= 858000000,
                .frequency_stepsize= 62500,
@@ -785,9 +794,9 @@ static struct dvb_frontend_ops lgdt3302_ops = {
 };
 
 static struct dvb_frontend_ops lgdt3303_ops = {
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
-               .type = FE_ATSC,
                .frequency_min= 54000000,
                .frequency_max= 858000000,
                .frequency_stepsize= 62500,
index bb37ed289a059542d2821b9612261a18e7751f1e..2cec8041a1068e7f0d7f6cef5a365d68434cfbed 100644 (file)
@@ -311,18 +311,18 @@ lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 
 
 static int
-lgs8gl5_set_frontend(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *p)
+lgs8gl5_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgs8gl5_state *state = fe->demodulator_priv;
 
        dprintk("%s\n", __func__);
 
-       if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ)
+       if (p->bandwidth_hz != 8000000)
                return -EINVAL;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -336,22 +336,21 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe,
 
 
 static int
-lgs8gl5_get_frontend(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *p)
+lgs8gl5_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct lgs8gl5_state *state = fe->demodulator_priv;
        u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
-       struct dvb_ofdm_parameters *o = &p->u.ofdm;
 
        p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
 
-       o->code_rate_HP = FEC_1_2;
-       o->code_rate_LP = FEC_7_8;
-       o->guard_interval = GUARD_INTERVAL_1_32;
-       o->transmission_mode = TRANSMISSION_MODE_2K;
-       o->constellation = QAM_64;
-       o->hierarchy_information = HIERARCHY_NONE;
-       o->bandwidth = BANDWIDTH_8_MHZ;
+       p->code_rate_HP = FEC_1_2;
+       p->code_rate_LP = FEC_7_8;
+       p->guard_interval = GUARD_INTERVAL_1_32;
+       p->transmission_mode = TRANSMISSION_MODE_2K;
+       p->modulation = QAM_64;
+       p->hierarchy = HIERARCHY_NONE;
+       p->bandwidth_hz = 8000000;
 
        return 0;
 }
@@ -413,9 +412,9 @@ EXPORT_SYMBOL(lgs8gl5_attach);
 
 
 static struct dvb_frontend_ops lgs8gl5_ops = {
+       .delsys = { SYS_DMBTH },
        .info = {
                .name                   = "Legend Silicon LGS-8GL5 DMB-TH",
-               .type                   = FE_OFDM,
                .frequency_min          = 474000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 10000,
index 1172b54689f81df3e7888e320f11c82f96c069d5..4de1d3520cd23b47492591f63ccff4c41196ee13 100644 (file)
@@ -669,16 +669,16 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
        return lgs8gxx_write_reg(priv, buf[0], buf[1]);
 }
 
-static int lgs8gxx_set_fe(struct dvb_frontend *fe,
-                         struct dvb_frontend_parameters *fe_params)
+static int lgs8gxx_set_fe(struct dvb_frontend *fe)
 {
+
        struct lgs8gxx_state *priv = fe->demodulator_priv;
 
        dprintk("%s\n", __func__);
 
        /* set frequency */
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, fe_params);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -691,9 +691,9 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe,
        return 0;
 }
 
-static int lgs8gxx_get_fe(struct dvb_frontend *fe,
-                         struct dvb_frontend_parameters *fe_params)
+static int lgs8gxx_get_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
        dprintk("%s\n", __func__);
 
        /* TODO: get real readings from device */
@@ -701,21 +701,21 @@ static int lgs8gxx_get_fe(struct dvb_frontend *fe,
        fe_params->inversion = INVERSION_OFF;
 
        /* bandwidth */
-       fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+       fe_params->bandwidth_hz = 8000000;
 
-       fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
-       fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
+       fe_params->code_rate_HP = FEC_AUTO;
+       fe_params->code_rate_LP = FEC_AUTO;
 
-       fe_params->u.ofdm.constellation = QAM_AUTO;
+       fe_params->modulation = QAM_AUTO;
 
        /* transmission mode */
-       fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+       fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
 
        /* guard interval */
-       fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+       fe_params->guard_interval = GUARD_INTERVAL_AUTO;
 
        /* hierarchy */
-       fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       fe_params->hierarchy = HIERARCHY_NONE;
 
        return 0;
 }
@@ -994,9 +994,9 @@ static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 
 static struct dvb_frontend_ops lgs8gxx_ops = {
+       .delsys = { SYS_DMBTH },
        .info = {
                .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
-               .type = FE_OFDM,
                .frequency_min = 474000000,
                .frequency_max = 858000000,
                .frequency_stepsize = 10000,
index c283112051b16cd6b9596c03644961ed0ff23f13..9ae40abfd71a170fe6940e372edefb1e0e558720 100644 (file)
@@ -1621,13 +1621,13 @@ err:
        return -EREMOTEIO;
 }
 
-static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe,
-                                       struct dvb_frontend_parameters *p)
+static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mb86a16_state *state = fe->demodulator_priv;
 
        state->frequency = p->frequency / 1000;
-       state->srate = p->u.qpsk.symbol_rate / 1000;
+       state->srate = p->symbol_rate / 1000;
 
        if (!mb86a16_set_fe(state)) {
                dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK");
@@ -1814,9 +1814,9 @@ static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops mb86a16_ops = {
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "Fujitsu MB86A16 DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 3000,
index 0f867a5055fb95b3368bc65ce744fd221caf8b83..7fa3e472cdcaf40e0af6d97a4515a6b383dea0dd 100644 (file)
@@ -61,244 +61,111 @@ static struct regdata mb86a20s_init[] = {
        { 0x70, 0xff },
        { 0x08, 0x01 },
        { 0x09, 0x3e },
-       { 0x50, 0xd1 },
-       { 0x51, 0x22 },
+       { 0x50, 0xd1 }, { 0x51, 0x22 },
        { 0x39, 0x01 },
        { 0x71, 0x00 },
-       { 0x28, 0x2a },
-       { 0x29, 0x00 },
-       { 0x2a, 0xff },
-       { 0x2b, 0x80 },
-       { 0x28, 0x20 },
-       { 0x29, 0x33 },
-       { 0x2a, 0xdf },
-       { 0x2b, 0xa9 },
+       { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
+       { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
+       { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
        { 0x3b, 0x21 },
        { 0x3c, 0x3a },
        { 0x01, 0x0d },
-       { 0x04, 0x08 },
-       { 0x05, 0x05 },
-       { 0x04, 0x0e },
-       { 0x05, 0x00 },
-       { 0x04, 0x0f },
-       { 0x05, 0x14 },
-       { 0x04, 0x0b },
-       { 0x05, 0x8c },
-       { 0x04, 0x00 },
-       { 0x05, 0x00 },
-       { 0x04, 0x01 },
-       { 0x05, 0x07 },
-       { 0x04, 0x02 },
-       { 0x05, 0x0f },
-       { 0x04, 0x03 },
-       { 0x05, 0xa0 },
-       { 0x04, 0x09 },
-       { 0x05, 0x00 },
-       { 0x04, 0x0a },
-       { 0x05, 0xff },
-       { 0x04, 0x27 },
-       { 0x05, 0x64 },
-       { 0x04, 0x28 },
-       { 0x05, 0x00 },
-       { 0x04, 0x1e },
-       { 0x05, 0xff },
-       { 0x04, 0x29 },
-       { 0x05, 0x0a },
-       { 0x04, 0x32 },
-       { 0x05, 0x0a },
-       { 0x04, 0x14 },
-       { 0x05, 0x02 },
-       { 0x04, 0x04 },
-       { 0x05, 0x00 },
-       { 0x04, 0x05 },
-       { 0x05, 0x22 },
-       { 0x04, 0x06 },
-       { 0x05, 0x0e },
-       { 0x04, 0x07 },
-       { 0x05, 0xd8 },
-       { 0x04, 0x12 },
-       { 0x05, 0x00 },
-       { 0x04, 0x13 },
-       { 0x05, 0xff },
+       { 0x04, 0x08 }, { 0x05, 0x05 },
+       { 0x04, 0x0e }, { 0x05, 0x00 },
+       { 0x04, 0x0f }, { 0x05, 0x14 },
+       { 0x04, 0x0b }, { 0x05, 0x8c },
+       { 0x04, 0x00 }, { 0x05, 0x00 },
+       { 0x04, 0x01 }, { 0x05, 0x07 },
+       { 0x04, 0x02 }, { 0x05, 0x0f },
+       { 0x04, 0x03 }, { 0x05, 0xa0 },
+       { 0x04, 0x09 }, { 0x05, 0x00 },
+       { 0x04, 0x0a }, { 0x05, 0xff },
+       { 0x04, 0x27 }, { 0x05, 0x64 },
+       { 0x04, 0x28 }, { 0x05, 0x00 },
+       { 0x04, 0x1e }, { 0x05, 0xff },
+       { 0x04, 0x29 }, { 0x05, 0x0a },
+       { 0x04, 0x32 }, { 0x05, 0x0a },
+       { 0x04, 0x14 }, { 0x05, 0x02 },
+       { 0x04, 0x04 }, { 0x05, 0x00 },
+       { 0x04, 0x05 }, { 0x05, 0x22 },
+       { 0x04, 0x06 }, { 0x05, 0x0e },
+       { 0x04, 0x07 }, { 0x05, 0xd8 },
+       { 0x04, 0x12 }, { 0x05, 0x00 },
+       { 0x04, 0x13 }, { 0x05, 0xff },
+       { 0x04, 0x15 }, { 0x05, 0x4e },
+       { 0x04, 0x16 }, { 0x05, 0x20 },
        { 0x52, 0x01 },
-       { 0x50, 0xa7 },
-       { 0x51, 0x00 },
-       { 0x50, 0xa8 },
-       { 0x51, 0xff },
-       { 0x50, 0xa9 },
-       { 0x51, 0xff },
-       { 0x50, 0xaa },
-       { 0x51, 0x00 },
-       { 0x50, 0xab },
-       { 0x51, 0xff },
-       { 0x50, 0xac },
-       { 0x51, 0xff },
-       { 0x50, 0xad },
-       { 0x51, 0x00 },
-       { 0x50, 0xae },
-       { 0x51, 0xff },
-       { 0x50, 0xaf },
-       { 0x51, 0xff },
+       { 0x50, 0xa7 }, { 0x51, 0xff },
+       { 0x50, 0xa8 }, { 0x51, 0xff },
+       { 0x50, 0xa9 }, { 0x51, 0xff },
+       { 0x50, 0xaa }, { 0x51, 0xff },
+       { 0x50, 0xab }, { 0x51, 0xff },
+       { 0x50, 0xac }, { 0x51, 0xff },
+       { 0x50, 0xad }, { 0x51, 0xff },
+       { 0x50, 0xae }, { 0x51, 0xff },
+       { 0x50, 0xaf }, { 0x51, 0xff },
        { 0x5e, 0x07 },
-       { 0x50, 0xdc },
-       { 0x51, 0x01 },
-       { 0x50, 0xdd },
-       { 0x51, 0xf4 },
-       { 0x50, 0xde },
-       { 0x51, 0x01 },
-       { 0x50, 0xdf },
-       { 0x51, 0xf4 },
-       { 0x50, 0xe0 },
-       { 0x51, 0x01 },
-       { 0x50, 0xe1 },
-       { 0x51, 0xf4 },
-       { 0x50, 0xb0 },
-       { 0x51, 0x07 },
-       { 0x50, 0xb2 },
-       { 0x51, 0xff },
-       { 0x50, 0xb3 },
-       { 0x51, 0xff },
-       { 0x50, 0xb4 },
-       { 0x51, 0xff },
-       { 0x50, 0xb5 },
-       { 0x51, 0xff },
-       { 0x50, 0xb6 },
-       { 0x51, 0xff },
-       { 0x50, 0xb7 },
-       { 0x51, 0xff },
-       { 0x50, 0x50 },
-       { 0x51, 0x02 },
-       { 0x50, 0x51 },
-       { 0x51, 0x04 },
+       { 0x50, 0xdc }, { 0x51, 0x01 },
+       { 0x50, 0xdd }, { 0x51, 0xf4 },
+       { 0x50, 0xde }, { 0x51, 0x01 },
+       { 0x50, 0xdf }, { 0x51, 0xf4 },
+       { 0x50, 0xe0 }, { 0x51, 0x01 },
+       { 0x50, 0xe1 }, { 0x51, 0xf4 },
+       { 0x50, 0xb0 }, { 0x51, 0x07 },
+       { 0x50, 0xb2 }, { 0x51, 0xff },
+       { 0x50, 0xb3 }, { 0x51, 0xff },
+       { 0x50, 0xb4 }, { 0x51, 0xff },
+       { 0x50, 0xb5 }, { 0x51, 0xff },
+       { 0x50, 0xb6 }, { 0x51, 0xff },
+       { 0x50, 0xb7 }, { 0x51, 0xff },
+       { 0x50, 0x50 }, { 0x51, 0x02 },
+       { 0x50, 0x51 }, { 0x51, 0x04 },
        { 0x45, 0x04 },
        { 0x48, 0x04 },
-       { 0x50, 0xd5 },
-       { 0x51, 0x01 },         /* Serial */
-       { 0x50, 0xd6 },
-       { 0x51, 0x1f },
-       { 0x50, 0xd2 },
-       { 0x51, 0x03 },
-       { 0x50, 0xd7 },
-       { 0x51, 0x3f },
+       { 0x50, 0xd5 }, { 0x51, 0x01 },         /* Serial */
+       { 0x50, 0xd6 }, { 0x51, 0x1f },
+       { 0x50, 0xd2 }, { 0x51, 0x03 },
+       { 0x50, 0xd7 }, { 0x51, 0x3f },
+       { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
+       { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
+       { 0x04, 0x40 }, { 0x05, 0x01 },
+       { 0x28, 0x00 }, { 0x29, 0x10 },
+       { 0x28, 0x05 }, { 0x29, 0x02 },
        { 0x1c, 0x01 },
-       { 0x28, 0x06 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x03 },
-       { 0x28, 0x07 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x0d },
-       { 0x28, 0x08 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x02 },
-       { 0x28, 0x09 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x01 },
-       { 0x28, 0x0a },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x21 },
-       { 0x28, 0x0b },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x29 },
-       { 0x28, 0x0c },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x16 },
-       { 0x28, 0x0d },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x31 },
-       { 0x28, 0x0e },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x0e },
-       { 0x28, 0x0f },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x4e },
-       { 0x28, 0x10 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x46 },
-       { 0x28, 0x11 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x0f },
-       { 0x28, 0x12 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x56 },
-       { 0x28, 0x13 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x35 },
-       { 0x28, 0x14 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x01 },
-       { 0x2b, 0xbe },
-       { 0x28, 0x15 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x01 },
-       { 0x2b, 0x84 },
-       { 0x28, 0x16 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x03 },
-       { 0x2b, 0xee },
-       { 0x28, 0x17 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x98 },
-       { 0x28, 0x18 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x9f },
-       { 0x28, 0x19 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x07 },
-       { 0x2b, 0xb2 },
-       { 0x28, 0x1a },
-       { 0x29, 0x00 },
-       { 0x2a, 0x06 },
-       { 0x2b, 0xc2 },
-       { 0x28, 0x1b },
-       { 0x29, 0x00 },
-       { 0x2a, 0x07 },
-       { 0x2b, 0x4a },
-       { 0x28, 0x1c },
-       { 0x29, 0x00 },
-       { 0x2a, 0x01 },
-       { 0x2b, 0xbc },
-       { 0x28, 0x1d },
-       { 0x29, 0x00 },
-       { 0x2a, 0x04 },
-       { 0x2b, 0xba },
-       { 0x28, 0x1e },
-       { 0x29, 0x00 },
-       { 0x2a, 0x06 },
-       { 0x2b, 0x14 },
-       { 0x50, 0x1e },
-       { 0x51, 0x5d },
-       { 0x50, 0x22 },
-       { 0x51, 0x00 },
-       { 0x50, 0x23 },
-       { 0x51, 0xc8 },
-       { 0x50, 0x24 },
-       { 0x51, 0x00 },
-       { 0x50, 0x25 },
-       { 0x51, 0xf0 },
-       { 0x50, 0x26 },
-       { 0x51, 0x00 },
-       { 0x50, 0x27 },
-       { 0x51, 0xc3 },
-       { 0x50, 0x39 },
-       { 0x51, 0x02 },
-       { 0x50, 0xd5 },
-       { 0x51, 0x01 },
+       { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
+       { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
+       { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
+       { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
+       { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
+       { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
+       { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
+       { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
+       { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
+       { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
+       { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
+       { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
+       { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
+       { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
+       { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
+       { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
+       { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
+       { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
+       { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
+       { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
+       { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
+       { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
+       { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
+       { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
+       { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
+       { 0x50, 0x1e }, { 0x51, 0x5d },
+       { 0x50, 0x22 }, { 0x51, 0x00 },
+       { 0x50, 0x23 }, { 0x51, 0xc8 },
+       { 0x50, 0x24 }, { 0x51, 0x00 },
+       { 0x50, 0x25 }, { 0x51, 0xf0 },
+       { 0x50, 0x26 }, { 0x51, 0x00 },
+       { 0x50, 0x27 }, { 0x51, 0xc3 },
+       { 0x50, 0x39 }, { 0x51, 0x02 },
+       { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
        { 0xd0, 0x00 },
 };
 
@@ -485,18 +352,23 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
        return 0;
 }
 
-static int mb86a20s_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int mb86a20s_set_frontend(struct dvb_frontend *fe)
 {
        struct mb86a20s_state *state = fe->demodulator_priv;
        int rc;
+#if 0
+       /*
+        * FIXME: Properly implement the set frontend properties
+        */
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+#endif
 
        dprintk("\n");
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        dprintk("Calling tuner set parameters\n");
-       fe->ops.tuner_ops.set_params(fe, p);
+       fe->ops.tuner_ops.set_params(fe);
 
        /*
         * Make it more reliable: if, for some reason, the initial
@@ -520,22 +392,212 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe,
        return rc;
 }
 
-static int mb86a20s_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int mb86a20s_get_modulation(struct mb86a20s_state *state,
+                                  unsigned layer)
+{
+       int rc;
+       static unsigned char reg[] = {
+               [0] = 0x86,     /* Layer A */
+               [1] = 0x8a,     /* Layer B */
+               [2] = 0x8e,     /* Layer C */
+       };
+
+       if (layer > ARRAY_SIZE(reg))
+               return -EINVAL;
+       rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+       if (rc < 0)
+               return rc;
+       rc = mb86a20s_readreg(state, 0x6e);
+       if (rc < 0)
+               return rc;
+       switch ((rc & 0x70) >> 4) {
+       case 0:
+               return DQPSK;
+       case 1:
+               return QPSK;
+       case 2:
+               return QAM_16;
+       case 3:
+               return QAM_64;
+       default:
+               return QAM_AUTO;
+       }
+}
+
+static int mb86a20s_get_fec(struct mb86a20s_state *state,
+                           unsigned layer)
 {
+       int rc;
 
-       /* FIXME: For now, it does nothing */
+       static unsigned char reg[] = {
+               [0] = 0x87,     /* Layer A */
+               [1] = 0x8b,     /* Layer B */
+               [2] = 0x8f,     /* Layer C */
+       };
 
-       fe->dtv_property_cache.bandwidth_hz = 6000000;
-       fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
-       fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
-       fe->dtv_property_cache.isdbt_partial_reception = 0;
+       if (layer > ARRAY_SIZE(reg))
+               return -EINVAL;
+       rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+       if (rc < 0)
+               return rc;
+       rc = mb86a20s_readreg(state, 0x6e);
+       if (rc < 0)
+               return rc;
+       switch (rc) {
+       case 0:
+               return FEC_1_2;
+       case 1:
+               return FEC_2_3;
+       case 2:
+               return FEC_3_4;
+       case 3:
+               return FEC_5_6;
+       case 4:
+               return FEC_7_8;
+       default:
+               return FEC_AUTO;
+       }
+}
+
+static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
+                                    unsigned layer)
+{
+       int rc;
+
+       static unsigned char reg[] = {
+               [0] = 0x88,     /* Layer A */
+               [1] = 0x8c,     /* Layer B */
+               [2] = 0x90,     /* Layer C */
+       };
+
+       if (layer > ARRAY_SIZE(reg))
+               return -EINVAL;
+       rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+       if (rc < 0)
+               return rc;
+       rc = mb86a20s_readreg(state, 0x6e);
+       if (rc < 0)
+               return rc;
+       if (rc > 3)
+               return -EINVAL; /* Not used */
+       return rc;
+}
+
+static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
+                                     unsigned layer)
+{
+       int rc, count;
+
+       static unsigned char reg[] = {
+               [0] = 0x89,     /* Layer A */
+               [1] = 0x8d,     /* Layer B */
+               [2] = 0x91,     /* Layer C */
+       };
+
+       if (layer > ARRAY_SIZE(reg))
+               return -EINVAL;
+       rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+       if (rc < 0)
+               return rc;
+       rc = mb86a20s_readreg(state, 0x6e);
+       if (rc < 0)
+               return rc;
+       count = (rc >> 4) & 0x0f;
+
+       return count;
+}
+
+static int mb86a20s_get_frontend(struct dvb_frontend *fe)
+{
+       struct mb86a20s_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       int i, rc;
+
+       /* Fixed parameters */
+       p->delivery_system = SYS_ISDBT;
+       p->bandwidth_hz = 6000000;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       /* Check for partial reception */
+       rc = mb86a20s_writereg(state, 0x6d, 0x85);
+       if (rc >= 0)
+               rc = mb86a20s_readreg(state, 0x6e);
+       if (rc >= 0)
+               p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
+
+       /* Get per-layer data */
+       p->isdbt_layer_enabled = 0;
+       for (i = 0; i < 3; i++) {
+               rc = mb86a20s_get_segment_count(state, i);
+                       if (rc >= 0 && rc < 14)
+                               p->layer[i].segment_count = rc;
+               if (rc == 0x0f)
+                       continue;
+               p->isdbt_layer_enabled |= 1 << i;
+               rc = mb86a20s_get_modulation(state, i);
+                       if (rc >= 0)
+                               p->layer[i].modulation = rc;
+               rc = mb86a20s_get_fec(state, i);
+                       if (rc >= 0)
+                               p->layer[i].fec = rc;
+               rc = mb86a20s_get_interleaving(state, i);
+                       if (rc >= 0)
+                               p->layer[i].interleaving = rc;
+       }
+
+       p->isdbt_sb_mode = 0;
+       rc = mb86a20s_writereg(state, 0x6d, 0x84);
+       if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
+               p->isdbt_sb_mode = 1;
+               /* At least, one segment should exist */
+               if (!p->isdbt_sb_segment_count)
+                       p->isdbt_sb_segment_count = 1;
+       } else
+               p->isdbt_sb_segment_count = 0;
+
+       /* Get transmission mode and guard interval */
+       p->transmission_mode = TRANSMISSION_MODE_AUTO;
+       p->guard_interval = GUARD_INTERVAL_AUTO;
+       rc = mb86a20s_readreg(state, 0x07);
+       if (rc >= 0) {
+               if ((rc & 0x60) == 0x20) {
+                       switch (rc & 0x0c >> 2) {
+                       case 0:
+                               p->transmission_mode = TRANSMISSION_MODE_2K;
+                               break;
+                       case 1:
+                               p->transmission_mode = TRANSMISSION_MODE_4K;
+                               break;
+                       case 2:
+                               p->transmission_mode = TRANSMISSION_MODE_8K;
+                               break;
+                       }
+               }
+               if (!(rc & 0x10)) {
+                       switch (rc & 0x3) {
+                       case 0:
+                               p->guard_interval = GUARD_INTERVAL_1_4;
+                               break;
+                       case 1:
+                               p->guard_interval = GUARD_INTERVAL_1_8;
+                               break;
+                       case 2:
+                               p->guard_interval = GUARD_INTERVAL_1_16;
+                               break;
+                       }
+               }
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
 
        return 0;
 }
 
 static int mb86a20s_tune(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *params,
+                       bool re_tune,
                        unsigned int mode_flags,
                        unsigned int *delay,
                        fe_status_t *status)
@@ -544,8 +606,8 @@ static int mb86a20s_tune(struct dvb_frontend *fe,
 
        dprintk("\n");
 
-       if (params != NULL)
-               rc = mb86a20s_set_frontend(fe, params);
+       if (re_tune)
+               rc = mb86a20s_set_frontend(fe);
 
        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
                mb86a20s_read_status(fe, status);
@@ -608,10 +670,10 @@ error:
 EXPORT_SYMBOL(mb86a20s_attach);
 
 static struct dvb_frontend_ops mb86a20s_ops = {
+       .delsys = { SYS_ISDBT },
        /* Use dib8000 values per default */
        .info = {
                .name = "Fujitsu mb86A20s",
-               .type = FE_OFDM,
                .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
                        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 |
index 83e6f1a1b7009cae02fb0c3579901a2d032be126..e20bf13aa860bb03f2d07945bf04497c6981eb2f 100644 (file)
@@ -531,9 +531,9 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
        return 0;
 }
 
-static int mt312_set_frontend(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *p)
+static int mt312_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[5], config_val;
@@ -553,16 +553,16 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
            || (p->inversion > INVERSION_ON))
                return -EINVAL;
 
-       if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
-           || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
+       if ((p->symbol_rate < fe->ops.info.symbol_rate_min)
+           || (p->symbol_rate > fe->ops.info.symbol_rate_max))
                return -EINVAL;
 
-       if ((p->u.qpsk.fec_inner < FEC_NONE)
-           || (p->u.qpsk.fec_inner > FEC_AUTO))
+       if ((p->fec_inner < FEC_NONE)
+           || (p->fec_inner > FEC_AUTO))
                return -EINVAL;
 
-       if ((p->u.qpsk.fec_inner == FEC_4_5)
-           || (p->u.qpsk.fec_inner == FEC_8_9))
+       if ((p->fec_inner == FEC_4_5)
+           || (p->fec_inner == FEC_8_9))
                return -EINVAL;
 
        switch (state->id) {
@@ -574,7 +574,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
                ret = mt312_readreg(state, CONFIG, &config_val);
                if (ret < 0)
                        return ret;
-               if (p->u.qpsk.symbol_rate >= 30000000) {
+               if (p->symbol_rate >= 30000000) {
                        /* Note that 30MS/s should use 90MHz */
                        if (state->freq_mult == 6) {
                                /* We are running 60MHz */
@@ -603,25 +603,25 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
        }
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        /* sr = (u16)(sr * 256.0 / 1000000.0) */
-       sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
+       sr = mt312_div(p->symbol_rate * 4, 15625);
 
        /* SYM_RATE */
        buf[0] = (sr >> 8) & 0x3f;
        buf[1] = (sr >> 0) & 0xff;
 
        /* VIT_MODE */
-       buf[2] = inv_tab[p->inversion] | fec_tab[p->u.qpsk.fec_inner];
+       buf[2] = inv_tab[p->inversion] | fec_tab[p->fec_inner];
 
        /* QPSK_CTRL */
        buf[3] = 0x40;          /* swap I and Q before QPSK demodulation */
 
-       if (p->u.qpsk.symbol_rate < 10000000)
+       if (p->symbol_rate < 10000000)
                buf[3] |= 0x04; /* use afc mode */
 
        /* GO */
@@ -636,9 +636,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
        return 0;
 }
 
-static int mt312_get_frontend(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *p)
+static int mt312_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mt312_state *state = fe->demodulator_priv;
        int ret;
 
@@ -646,11 +646,11 @@ static int mt312_get_frontend(struct dvb_frontend *fe,
        if (ret < 0)
                return ret;
 
-       ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate);
+       ret = mt312_get_symbol_rate(state, &p->symbol_rate);
        if (ret < 0)
                return ret;
 
-       ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner);
+       ret = mt312_get_code_rate(state, &p->fec_inner);
        if (ret < 0)
                return ret;
 
@@ -738,10 +738,9 @@ static void mt312_release(struct dvb_frontend *fe)
 
 #define MT312_SYS_CLK          90000000UL      /* 90 MHz */
 static struct dvb_frontend_ops mt312_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name = "Zarlink ???? DVB-S",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                /* FIXME: adjust freq to real used xtal */
index 319672f8e1a70c8ac04ec8940f1698d29ccf7bdc..2c3b50e828d7dbe7fa6e3761bc462bfa0f7827bc 100644 (file)
@@ -111,20 +111,20 @@ static int mt352_sleep(struct dvb_frontend* fe)
 }
 
 static void mt352_calc_nominal_rate(struct mt352_state* state,
-                                   enum fe_bandwidth bandwidth,
+                                   u32 bandwidth,
                                    unsigned char *buf)
 {
        u32 adc_clock = 20480; /* 20.340 MHz */
        u32 bw,value;
 
        switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                bw = 6;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                bw = 7;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
        default:
                bw = 8;
                break;
@@ -166,15 +166,14 @@ static void mt352_calc_input_freq(struct mt352_state* state,
        buf[1] = lsb(value);
 }
 
-static int mt352_set_parameters(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *param)
+static int mt352_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *op = &fe->dtv_property_cache;
        struct mt352_state* state = fe->demodulator_priv;
        unsigned char buf[13];
        static unsigned char tuner_go[] = { 0x5d, 0x01 };
        static unsigned char fsm_go[]   = { 0x5e, 0x01 };
        unsigned int tps = 0;
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
 
        switch (op->code_rate_HP) {
                case FEC_2_3:
@@ -213,14 +212,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
                case FEC_AUTO:
                        break;
                case FEC_NONE:
-                       if (op->hierarchy_information == HIERARCHY_AUTO ||
-                           op->hierarchy_information == HIERARCHY_NONE)
+                       if (op->hierarchy == HIERARCHY_AUTO ||
+                           op->hierarchy == HIERARCHY_NONE)
                                break;
                default:
                        return -EINVAL;
        }
 
-       switch (op->constellation) {
+       switch (op->modulation) {
                case QPSK:
                        break;
                case QAM_AUTO:
@@ -262,7 +261,7 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
                        return -EINVAL;
        }
 
-       switch (op->hierarchy_information) {
+       switch (op->hierarchy) {
                case HIERARCHY_AUTO:
                case HIERARCHY_NONE:
                        break;
@@ -288,12 +287,12 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
        buf[3] = 0x50;  // old
 //     buf[3] = 0xf4;  // pinnacle
 
-       mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
+       mt352_calc_nominal_rate(state, op->bandwidth_hz, buf+4);
        mt352_calc_input_freq(state, buf+6);
 
        if (state->config.no_tuner) {
                if (fe->ops.tuner_ops.set_params) {
-                       fe->ops.tuner_ops.set_params(fe, param);
+                       fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl)
                                fe->ops.i2c_gate_ctrl(fe, 0);
                }
@@ -302,7 +301,7 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
                _mt352_write(fe, fsm_go, 2);
        } else {
                if (fe->ops.tuner_ops.calc_regs) {
-                       fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
+                       fe->ops.tuner_ops.calc_regs(fe, buf+8, 5);
                        buf[8] <<= 1;
                        _mt352_write(fe, buf, sizeof(buf));
                        _mt352_write(fe, tuner_go, 2);
@@ -312,14 +311,13 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
        return 0;
 }
 
-static int mt352_get_parameters(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *param)
+static int mt352_get_parameters(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *op = &fe->dtv_property_cache;
        struct mt352_state* state = fe->demodulator_priv;
        u16 tps;
        u16 div;
        u8 trl;
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
        static const u8 tps_fec_to_api[8] =
        {
                FEC_1_2,
@@ -348,16 +346,16 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
        switch ( (tps >> 13) & 3)
        {
                case 0:
-                       op->constellation = QPSK;
+                       op->modulation = QPSK;
                        break;
                case 1:
-                       op->constellation = QAM_16;
+                       op->modulation = QAM_16;
                        break;
                case 2:
-                       op->constellation = QAM_64;
+                       op->modulation = QAM_64;
                        break;
                default:
-                       op->constellation = QAM_AUTO;
+                       op->modulation = QAM_AUTO;
                        break;
        }
 
@@ -385,36 +383,36 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
        switch ( (tps >> 10) & 7)
        {
                case 0:
-                       op->hierarchy_information = HIERARCHY_NONE;
+                       op->hierarchy = HIERARCHY_NONE;
                        break;
                case 1:
-                       op->hierarchy_information = HIERARCHY_1;
+                       op->hierarchy = HIERARCHY_1;
                        break;
                case 2:
-                       op->hierarchy_information = HIERARCHY_2;
+                       op->hierarchy = HIERARCHY_2;
                        break;
                case 3:
-                       op->hierarchy_information = HIERARCHY_4;
+                       op->hierarchy = HIERARCHY_4;
                        break;
                default:
-                       op->hierarchy_information = HIERARCHY_AUTO;
+                       op->hierarchy = HIERARCHY_AUTO;
                        break;
        }
 
-       param->frequency = ( 500 * (div - IF_FREQUENCYx6) ) / 3 * 1000;
+       op->frequency = (500 * (div - IF_FREQUENCYx6)) / 3 * 1000;
 
        if (trl == 0x72)
-               op->bandwidth = BANDWIDTH_8_MHZ;
+               op->bandwidth_hz = 8000000;
        else if (trl == 0x64)
-               op->bandwidth = BANDWIDTH_7_MHZ;
+               op->bandwidth_hz = 7000000;
        else
-               op->bandwidth = BANDWIDTH_6_MHZ;
+               op->bandwidth_hz = 6000000;
 
 
        if (mt352_read_register(state, STATUS_2) & 0x02)
-               param->inversion = INVERSION_OFF;
+               op->inversion = INVERSION_OFF;
        else
-               param->inversion = INVERSION_ON;
+               op->inversion = INVERSION_ON;
 
        return 0;
 }
@@ -569,10 +567,9 @@ error:
 }
 
 static struct dvb_frontend_ops mt352_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Zarlink MT352 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 174000000,
                .frequency_max          = 862000000,
                .frequency_stepsize     = 166667,
index eac20650499fb510217a1ccf4bba9598083f60c7..49ca78d883b18031ec110a6329be86bf49c9acbe 100644 (file)
@@ -528,9 +528,9 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
        return 0;
 };
 
-static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
-                                            struct dvb_frontend_parameters *p)
+static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct nxt200x_state* state = fe->demodulator_priv;
        u8 buf[5];
 
@@ -546,7 +546,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
        }
 
        /* set additional params */
-       switch (p->u.vsb.modulation) {
+       switch (p->modulation) {
                case QAM_64:
                case QAM_256:
                        /* Set punctured clock for QAM */
@@ -566,7 +566,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
 
        if (fe->ops.tuner_ops.calc_regs) {
                /* get tuning information */
-               fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+               fe->ops.tuner_ops.calc_regs(fe, buf, 5);
 
                /* write frequency information */
                nxt200x_writetuner(state, buf);
@@ -576,7 +576,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
        nxt200x_agc_reset(state);
 
        /* set target power level */
-       switch (p->u.vsb.modulation) {
+       switch (p->modulation) {
                case QAM_64:
                case QAM_256:
                        buf[0] = 0x74;
@@ -620,7 +620,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
        }
 
        /* write sdmx input */
-       switch (p->u.vsb.modulation) {
+       switch (p->modulation) {
                case QAM_64:
                                buf[0] = 0x68;
                                break;
@@ -714,7 +714,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
        }
 
        /* write agc ucgp0 */
-       switch (p->u.vsb.modulation) {
+       switch (p->modulation) {
                case QAM_64:
                                buf[0] = 0x02;
                                break;
@@ -1203,10 +1203,9 @@ error:
 }
 
 static struct dvb_frontend_ops nxt200x_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name = "Nextwave NXT200X VSB/QAM frontend",
-               .type = FE_ATSC,
                .frequency_min =  54000000,
                .frequency_max = 860000000,
                .frequency_stepsize = 166666,   /* stepsize is just a guess */
index 6599b8fea9e9ad0d2c3bad2560565670b5e2486c..90ae6c72c0e3c085f792820dfbc995e831a588c9 100644 (file)
@@ -81,22 +81,21 @@ static void nxt6000_reset(struct nxt6000_state* state)
        nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
 }
 
-static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth)
+static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth)
 {
        u16 nominal_rate;
        int result;
 
        switch (bandwidth) {
-
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                nominal_rate = 0x55B7;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                nominal_rate = 0x6400;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                nominal_rate = 0x7249;
                break;
 
@@ -457,23 +456,31 @@ static int nxt6000_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
+static int nxt6000_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct nxt6000_state* state = fe->demodulator_priv;
        int result;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
+       result = nxt6000_set_bandwidth(state, p->bandwidth_hz);
+       if (result < 0)
                return result;
-       if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0)
+
+       result = nxt6000_set_guard_interval(state, p->guard_interval);
+       if (result < 0)
                return result;
-       if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0)
+
+       result = nxt6000_set_transmission_mode(state, p->transmission_mode);
+       if (result < 0)
                return result;
-       if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
+
+       result = nxt6000_set_inversion(state, p->inversion);
+       if (result < 0)
                return result;
 
        msleep(500);
@@ -566,10 +573,9 @@ error:
 }
 
 static struct dvb_frontend_ops nxt6000_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "NxtWave NXT6000 DVB-T",
-               .type = FE_OFDM,
                .frequency_min = 0,
                .frequency_max = 863250000,
                .frequency_stepsize = 62500,
index 38e67accb8c360af874fc9b3d57804c523d4a34a..5ef921823c1537088dd22914fdcfff41553412a4 100644 (file)
@@ -306,9 +306,9 @@ static int modulation_fw_class(fe_modulation_t modulation)
        }
 }
 
-static int or51132_set_parameters(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *param)
+static int or51132_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        int ret;
        struct or51132_state* state = fe->demodulator_priv;
        const struct firmware *fw;
@@ -317,8 +317,8 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
 
        /* Upload new firmware only if we need a different one */
        if (modulation_fw_class(state->current_modulation) !=
-           modulation_fw_class(param->u.vsb.modulation)) {
-               switch(modulation_fw_class(param->u.vsb.modulation)) {
+           modulation_fw_class(p->modulation)) {
+               switch (modulation_fw_class(p->modulation)) {
                case MOD_FWCLASS_VSB:
                        dprintk("set_parameters VSB MODE\n");
                        fwname = OR51132_VSB_FIRMWARE;
@@ -335,7 +335,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
                        break;
                default:
                        printk("or51132: Modulation type(%d) UNSUPPORTED\n",
-                              param->u.vsb.modulation);
+                              p->modulation);
                        return -1;
                }
                printk("or51132: Waiting for firmware upload(%s)...\n",
@@ -357,13 +357,13 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
                state->config->set_ts_params(fe, clock_mode);
        }
        /* Change only if we are actually changing the modulation */
-       if (state->current_modulation != param->u.vsb.modulation) {
-               state->current_modulation = param->u.vsb.modulation;
+       if (state->current_modulation != p->modulation) {
+               state->current_modulation = p->modulation;
                or51132_setmode(fe);
        }
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
@@ -371,13 +371,13 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
        or51132_setmode(fe);
 
        /* Update current frequency */
-       state->current_frequency = param->frequency;
+       state->current_frequency = p->frequency;
        return 0;
 }
 
-static int or51132_get_parameters(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *param)
+static int or51132_get_parameters(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct or51132_state* state = fe->demodulator_priv;
        int status;
        int retry = 1;
@@ -389,21 +389,28 @@ start:
                return -EREMOTEIO;
        }
        switch(status&0xff) {
-               case 0x06: param->u.vsb.modulation = VSB_8; break;
-               case 0x43: param->u.vsb.modulation = QAM_64; break;
-               case 0x45: param->u.vsb.modulation = QAM_256; break;
-               default:
-                       if (retry--) goto start;
-                       printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
-                              status&0xff);
-                       return -EREMOTEIO;
+       case 0x06:
+               p->modulation = VSB_8;
+               break;
+       case 0x43:
+               p->modulation = QAM_64;
+               break;
+       case 0x45:
+               p->modulation = QAM_256;
+               break;
+       default:
+               if (retry--)
+                       goto start;
+               printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+                      status&0xff);
+               return -EREMOTEIO;
        }
 
        /* FIXME: Read frequency from frontend, take AFC into account */
-       param->frequency = state->current_frequency;
+       p->frequency = state->current_frequency;
 
        /* FIXME: How to read inversion setting? Receiver 6 register? */
-       param->inversion = INVERSION_AUTO;
+       p->inversion = INVERSION_AUTO;
 
        return 0;
 }
@@ -579,10 +586,9 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
 }
 
 static struct dvb_frontend_ops or51132_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name                   = "Oren OR51132 VSB/QAM Frontend",
-               .type                   = FE_ATSC,
                .frequency_min          = 44000000,
                .frequency_max          = 958000000,
                .frequency_stepsize     = 166666,
index c709ce6771c86ca831e9e17e1677e03da0b05e7c..c625b57b4333e499827ff9e024d98227eda78775 100644 (file)
@@ -218,15 +218,15 @@ static int or51211_setmode(struct dvb_frontend* fe, int mode)
        return 0;
 }
 
-static int or51211_set_parameters(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *param)
+static int or51211_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct or51211_state* state = fe->demodulator_priv;
 
        /* Change only if we are actually changing the channel */
-       if (state->current_frequency != param->frequency) {
+       if (state->current_frequency != p->frequency) {
                if (fe->ops.tuner_ops.set_params) {
-                       fe->ops.tuner_ops.set_params(fe, param);
+                       fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
                }
 
@@ -234,7 +234,7 @@ static int or51211_set_parameters(struct dvb_frontend* fe,
                or51211_setmode(fe,0);
 
                /* Update current frequency */
-               state->current_frequency = param->frequency;
+               state->current_frequency = p->frequency;
        }
        return 0;
 }
@@ -544,10 +544,9 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
 }
 
 static struct dvb_frontend_ops or51211_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name               = "Oren OR51211 VSB Frontend",
-               .type               = FE_ATSC,
                .frequency_min      = 44000000,
                .frequency_max      = 958000000,
                .frequency_stepsize = 166666,
index 0e2f61a8978ffe3febef2321bd1e2d5fcd790cbf..f71b06221e14c44c93cf934988c21b20fcf3f596 100644 (file)
@@ -631,9 +631,9 @@ static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe)
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *p)
+static int s5h1409_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1409_state *state = fe->demodulator_priv;
 
        dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -642,12 +642,12 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
 
        state->current_frequency = p->frequency;
 
-       s5h1409_enable_modulation(fe, p->u.vsb.modulation);
+       s5h1409_enable_modulation(fe, p->modulation);
 
        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);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -879,7 +879,36 @@ static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
 static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
                                        u16 *signal_strength)
 {
-       return s5h1409_read_snr(fe, signal_strength);
+       /* borrowed from lgdt330x.c
+        *
+        * Calculate strength from SNR up to 35dB
+        * Even though the SNR can go higher than 35dB,
+        * there is some comfort factor in having a range of
+        * strong signals that can show at 100%
+        */
+       u16 snr;
+       u32 tmp;
+       int ret = s5h1409_read_snr(fe, &snr);
+
+       *signal_strength = 0;
+
+       if (0 == ret) {
+               /* The following calculation method was chosen
+                * purely for the sake of code re-use from the
+                * other demod drivers that use this method */
+
+               /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+               tmp = (snr * ((1 << 24) / 10));
+
+               /* Convert from 8.24 fixed-point to
+                * scale the range 0 - 35*2^24 into 0 - 65535*/
+               if (tmp >= 8960 * 0x10000)
+                       *signal_strength = 0xffff;
+               else
+                       *signal_strength = tmp / 8960;
+       }
+
+       return ret;
 }
 
 static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -896,13 +925,13 @@ static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
        return s5h1409_read_ucblocks(fe, ber);
 }
 
-static int s5h1409_get_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int s5h1409_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1409_state *state = fe->demodulator_priv;
 
        p->frequency = state->current_frequency;
-       p->u.vsb.modulation = state->current_modulation;
+       p->modulation = state->current_modulation;
 
        return 0;
 }
@@ -967,10 +996,9 @@ error:
 EXPORT_SYMBOL(s5h1409_attach);
 
 static struct dvb_frontend_ops s5h1409_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name                   = "Samsung S5H1409 QAM/8VSB Frontend",
-               .type                   = FE_ATSC,
                .frequency_min          = 54000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 62500,
index d8adf1e32019a9f7b62a712d693dd242ee79e036..6cc4b7a9dd60d588c3bc665080eeae68b78c8c21 100644 (file)
@@ -585,9 +585,9 @@ static int s5h1411_register_reset(struct dvb_frontend *fe)
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1411_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int s5h1411_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1411_state *state = fe->demodulator_priv;
 
        dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -596,13 +596,13 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
 
        state->current_frequency = p->frequency;
 
-       s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+       s5h1411_enable_modulation(fe, p->modulation);
 
        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);
+               fe->ops.tuner_ops.set_params(fe);
 
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
@@ -794,7 +794,36 @@ static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
 static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
        u16 *signal_strength)
 {
-       return s5h1411_read_snr(fe, signal_strength);
+       /* borrowed from lgdt330x.c
+        *
+        * Calculate strength from SNR up to 35dB
+        * Even though the SNR can go higher than 35dB,
+        * there is some comfort factor in having a range of
+        * strong signals that can show at 100%
+        */
+       u16 snr;
+       u32 tmp;
+       int ret = s5h1411_read_snr(fe, &snr);
+
+       *signal_strength = 0;
+
+       if (0 == ret) {
+               /* The following calculation method was chosen
+                * purely for the sake of code re-use from the
+                * other demod drivers that use this method */
+
+               /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+               tmp = (snr * ((1 << 24) / 10));
+
+               /* Convert from 8.24 fixed-point to
+                * scale the range 0 - 35*2^24 into 0 - 65535*/
+               if (tmp >= 8960 * 0x10000)
+                       *signal_strength = 0xffff;
+               else
+                       *signal_strength = tmp / 8960;
+       }
+
+       return ret;
 }
 
 static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -811,13 +840,13 @@ static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
        return s5h1411_read_ucblocks(fe, ber);
 }
 
-static int s5h1411_get_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int s5h1411_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1411_state *state = fe->demodulator_priv;
 
        p->frequency = state->current_frequency;
-       p->u.vsb.modulation = state->current_modulation;
+       p->modulation = state->current_modulation;
 
        return 0;
 }
@@ -886,10 +915,9 @@ error:
 EXPORT_SYMBOL(s5h1411_attach);
 
 static struct dvb_frontend_ops s5h1411_ops = {
-
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name                   = "Samsung S5H1411 QAM/8VSB Frontend",
-               .type                   = FE_ATSC,
                .frequency_min          = 54000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 62500,
index 3879d2e378aa73da4ac1b923a7e163c6c54a48a6..2322257c69ae33bb5af5ed2ea200b82a671ff18a 100644 (file)
@@ -472,15 +472,15 @@ static void s5h1420_reset(struct s5h1420_state* state)
 }
 
 static void s5h1420_setsymbolrate(struct s5h1420_state* state,
-                                 struct dvb_frontend_parameters *p)
+                                 struct dtv_frontend_properties *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 < 29000000)
+       val = ((u64) p->symbol_rate / 1000ULL) * (1ULL<<24);
+       if (p->symbol_rate < 29000000)
                val *= 2;
        do_div(val, (state->fclk / 1000));
 
@@ -543,7 +543,7 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
 }
 
 static void s5h1420_setfec_inversion(struct s5h1420_state* state,
-                                    struct dvb_frontend_parameters *p)
+                                    struct dtv_frontend_properties *p)
 {
        u8 inversion = 0;
        u8 vit08, vit09;
@@ -555,11 +555,11 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
        else if (p->inversion == INVERSION_ON)
                inversion = state->config->invert ? 0 : 0x08;
 
-       if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+       if ((p->fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
                vit08 = 0x3f;
                vit09 = 0;
        } else {
-               switch(p->u.qpsk.fec_inner) {
+               switch (p->fec_inner) {
                case FEC_1_2:
                        vit08 = 0x01; vit09 = 0x10;
                        break;
@@ -628,9 +628,9 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
        return INVERSION_OFF;
 }
 
-static int s5h1420_set_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *p)
+static int s5h1420_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1420_state* state = fe->demodulator_priv;
        int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
@@ -639,17 +639,16 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        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)) {
+                       (state->fec_inner == p->fec_inner) &&
+                       (state->symbol_rate == p->symbol_rate)) {
 
                if (fe->ops.tuner_ops.set_params) {
-                       fe->ops.tuner_ops.set_params(fe, p);
+                       fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
                }
                if (fe->ops.tuner_ops.get_frequency) {
@@ -669,13 +668,13 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        s5h1420_reset(state);
 
        /* set s5h1420 fclk PLL according to desired symbol rate */
-       if (p->u.qpsk.symbol_rate > 33000000)
+       if (p->symbol_rate > 33000000)
                state->fclk = 80000000;
-       else if (p->u.qpsk.symbol_rate > 28500000)
+       else if (p->symbol_rate > 28500000)
                state->fclk = 59000000;
-       else if (p->u.qpsk.symbol_rate > 25000000)
+       else if (p->symbol_rate > 25000000)
                state->fclk = 86000000;
-       else if (p->u.qpsk.symbol_rate > 1900000)
+       else if (p->symbol_rate > 1900000)
                state->fclk = 88000000;
        else
                state->fclk = 44000000;
@@ -705,7 +704,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
 
        /* TODO DC offset removal, config parameter ? */
-       if (p->u.qpsk.symbol_rate > 29000000)
+       if (p->symbol_rate > 29000000)
                s5h1420_writereg(state, QPSK01, 0xae | 0x10);
        else
                s5h1420_writereg(state, QPSK01, 0xac | 0x10);
@@ -718,15 +717,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        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)
+       if (p->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)
+       if (p->symbol_rate >= 8000000)
                s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
-       else if (p->u.qpsk.symbol_rate >= 4000000)
+       else if (p->symbol_rate >= 4000000)
                s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
        else
                s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
@@ -744,7 +743,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
 
        /* set tuner PLL */
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
                s5h1420_setfreqoffset(state, 0);
@@ -757,8 +756,8 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        /* 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->fec_inner = p->fec_inner;
+       state->symbol_rate = p->symbol_rate;
        state->postlocked = 0;
        state->tunedfreq = p->frequency;
 
@@ -766,15 +765,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
-static int s5h1420_get_frontend(struct dvb_frontend* fe,
-                               struct dvb_frontend_parameters *p)
+static int s5h1420_get_frontend(struct dvb_frontend* fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s5h1420_state* state = fe->demodulator_priv;
 
        p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
        p->inversion = s5h1420_getinversion(state);
-       p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state);
-       p->u.qpsk.fec_inner = s5h1420_getfec(state);
+       p->symbol_rate = s5h1420_getsymbolrate(state);
+       p->fec_inner = s5h1420_getfec(state);
 
        return 0;
 }
@@ -782,29 +781,30 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe,
 static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
                                     struct dvb_frontend_tune_settings* fesettings)
 {
-       if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       if (p->symbol_rate > 20000000) {
                fesettings->min_delay_ms = 50;
                fesettings->step_size = 2000;
                fesettings->max_drift = 8000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+       } else if (p->symbol_rate > 12000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 1500;
                fesettings->max_drift = 9000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+       } else if (p->symbol_rate > 8000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 1000;
                fesettings->max_drift = 8000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+       } else if (p->symbol_rate > 4000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 500;
                fesettings->max_drift = 7000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+       } else if (p->symbol_rate > 2000000) {
                fesettings->min_delay_ms = 200;
-               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->step_size = (p->symbol_rate / 8000);
                fesettings->max_drift = 14 * fesettings->step_size;
        } else {
                fesettings->min_delay_ms = 200;
-               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->step_size = (p->symbol_rate / 8000);
                fesettings->max_drift = 18 * fesettings->step_size;
        }
 
@@ -937,10 +937,9 @@ error:
 EXPORT_SYMBOL(s5h1420_attach);
 
 static struct dvb_frontend_ops s5h1420_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
-               .type     = FE_QPSK,
                .frequency_min    = 950000,
                .frequency_max    = 2150000,
                .frequency_stepsize = 125,     /* kHz for QPSK frontends */
index 0c6dcb90d16826686d97f81be8aca55da555407b..8352ce1c95563798c06f86e4b0f68bec85c6cd7f 100644 (file)
@@ -178,9 +178,9 @@ static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1432_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int s5h1432_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        u32 dvb_bandwidth = 8;
        struct s5h1432_state *state = fe->demodulator_priv;
 
@@ -188,26 +188,26 @@ static int s5h1432_set_frontend(struct dvb_frontend *fe,
                /*current_frequency = p->frequency; */
                /*state->current_frequency = p->frequency; */
        } else {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                msleep(300);
                s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
-               switch (p->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
+               switch (p->bandwidth_hz) {
+               case 6000000:
                        dvb_bandwidth = 6;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        dvb_bandwidth = 7;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
-               case BANDWIDTH_8_MHZ:
+               case 8000000:
                        dvb_bandwidth = 8;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
                default:
                        return 0;
                }
-               /*fe->ops.tuner_ops.set_params(fe, p); */
+               /*fe->ops.tuner_ops.set_params(fe); */
 /*Soft Reset chip*/
                msleep(30);
                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
@@ -215,23 +215,23 @@ static int s5h1432_set_frontend(struct dvb_frontend *fe,
                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
 
                s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
-               switch (p->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
+               switch (p->bandwidth_hz) {
+               case 6000000:
                        dvb_bandwidth = 6;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        dvb_bandwidth = 7;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
-               case BANDWIDTH_8_MHZ:
+               case 8000000:
                        dvb_bandwidth = 8;
                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
                        break;
                default:
                        return 0;
                }
-               /*fe->ops.tuner_ops.set_params(fe,p); */
+               /*fe->ops.tuner_ops.set_params(fe); */
                /*Soft Reset chip*/
                msleep(30);
                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
@@ -329,12 +329,6 @@ static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
        return 0;
 }
 
-static int s5h1432_get_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
-{
-       return 0;
-}
-
 static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
                                     struct dvb_frontend_tune_settings *tune)
 {
@@ -381,10 +375,9 @@ error:
 EXPORT_SYMBOL(s5h1432_attach);
 
 static struct dvb_frontend_ops s5h1432_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                 .name = "Samsung s5h1432 DVB-T Frontend",
-                .type = FE_OFDM,
                 .frequency_min = 177000000,
                 .frequency_max = 858000000,
                 .frequency_stepsize = 166666,
@@ -397,7 +390,6 @@ static struct dvb_frontend_ops s5h1432_ops = {
        .init = s5h1432_init,
        .sleep = s5h1432_sleep,
        .set_frontend = s5h1432_set_frontend,
-       .get_frontend = s5h1432_get_frontend,
        .get_tune_settings = s5h1432_get_tune_settings,
        .read_status = s5h1432_read_status,
        .read_ber = s5h1432_read_ber,
index ca0103d5f148ae38938e6651bbf272ec13020dbc..cd2288c07147a7614d7d37ef0022400e6b05d318 100644 (file)
@@ -262,9 +262,9 @@ static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
        s921_i2c_writeregdata(state, state->config->demod_address, \
        regdata, ARRAY_SIZE(regdata))
 
-static int s921_pll_tune(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int s921_pll_tune(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s921_state *state = fe->demodulator_priv;
        int band, rc, i;
        unsigned long f_offset;
@@ -414,9 +414,9 @@ static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
        return 0;
 }
 
-static int s921_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int s921_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s921_state *state = fe->demodulator_priv;
        int rc;
 
@@ -424,7 +424,7 @@ static int s921_set_frontend(struct dvb_frontend *fe,
 
        /* FIXME: We don't know how to use non-auto mode */
 
-       rc = s921_pll_tune(fe, p);
+       rc = s921_pll_tune(fe);
        if (rc < 0)
                return rc;
 
@@ -433,19 +433,20 @@ static int s921_set_frontend(struct dvb_frontend *fe,
        return 0;
 }
 
-static int s921_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int s921_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct s921_state *state = fe->demodulator_priv;
 
        /* FIXME: Probably it is possible to get it from regs f1 and f2 */
        p->frequency = state->currentfreq;
+       p->delivery_system = SYS_ISDBT;
 
        return 0;
 }
 
 static int s921_tune(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *params,
+                       bool re_tune,
                        unsigned int mode_flags,
                        unsigned int *delay,
                        fe_status_t *status)
@@ -454,8 +455,8 @@ static int s921_tune(struct dvb_frontend *fe,
 
        dprintk("\n");
 
-       if (params != NULL)
-               rc = s921_set_frontend(fe, params);
+       if (re_tune)
+               rc = s921_set_frontend(fe);
 
        if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
                s921_read_status(fe, status);
@@ -510,10 +511,10 @@ rcor:
 EXPORT_SYMBOL(s921_attach);
 
 static struct dvb_frontend_ops s921_ops = {
+       .delsys = { SYS_ISDBT },
        /* Use dib8000 values per default */
        .info = {
                .name = "Sharp S921",
-               .type = FE_OFDM,
                .frequency_min = 470000000,
                /*
                 * Max should be 770MHz instead, according with Sharp docs,
index 4b0c99a08a852ebb01b155cb7c21d27c9b969cd4..a68a64800df77ff7123ae6d18434820d6c95a2b4 100644 (file)
@@ -690,20 +690,7 @@ static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
        return status;
 }
 
-static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
-static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
-static int si21xx_set_frontend(struct dvb_frontend *fe,
-                                       struct dvb_frontend_parameters *dfp)
+static int si21xx_set_frontend(struct dvb_frontend *fe)
 {
        struct si21xx_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -877,10 +864,9 @@ static void si21xx_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops si21xx_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "SL SI21XX DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 125,   /* kHz for QPSK frontends */
@@ -908,8 +894,6 @@ static struct dvb_frontend_ops si21xx_ops = {
        .set_tone = si21xx_set_tone,
        .set_voltage = si21xx_set_voltage,
 
-       .set_property = si21xx_set_property,
-       .get_property = si21xx_get_property,
        .set_frontend = si21xx_set_frontend,
 };
 
index b85eb60a893e34954a313382a2fad0b5d8a88499..e37274c8f14e004c6058c64d053304704f8196ee 100644 (file)
@@ -168,13 +168,13 @@ static int sp8870_read_data_valid_signal(struct sp8870_state* state)
        return (sp8870_readreg(state, 0x0D02) > 0);
 }
 
-static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
+static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
 {
        int known_parameters = 1;
 
        *reg0xc05 = 0x000;
 
-       switch (p->u.ofdm.constellation) {
+       switch (p->modulation) {
        case QPSK:
                break;
        case QAM_16:
@@ -190,7 +190,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
                return -EINVAL;
        };
 
-       switch (p->u.ofdm.hierarchy_information) {
+       switch (p->hierarchy) {
        case HIERARCHY_NONE:
                break;
        case HIERARCHY_1:
@@ -209,7 +209,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
                return -EINVAL;
        };
 
-       switch (p->u.ofdm.code_rate_HP) {
+       switch (p->code_rate_HP) {
        case FEC_1_2:
                break;
        case FEC_2_3:
@@ -245,9 +245,9 @@ static int sp8870_wake_up(struct sp8870_state* state)
        return sp8870_writereg(state, 0xC18, 0x00D);
 }
 
-static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
-                                          struct dvb_frontend_parameters *p)
+static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct sp8870_state* state = fe->demodulator_priv;
        int  err;
        u16 reg0xc05;
@@ -260,7 +260,7 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
 
        // set tuner parameters
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
@@ -277,15 +277,15 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
        sp8870_writereg(state, 0x030A, 0x0000);
 
        // filter for 6/7/8 Mhz channel
-       if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+       if (p->bandwidth_hz == 6000000)
                sp8870_writereg(state, 0x0311, 0x0002);
-       else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+       else if (p->bandwidth_hz == 7000000)
                sp8870_writereg(state, 0x0311, 0x0001);
        else
                sp8870_writereg(state, 0x0311, 0x0000);
 
        // scan order: 2k first = 0x0000, 8k first = 0x0001
-       if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
+       if (p->transmission_mode == TRANSMISSION_MODE_2K)
                sp8870_writereg(state, 0x0338, 0x0000);
        else
                sp8870_writereg(state, 0x0338, 0x0001);
@@ -459,8 +459,9 @@ 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)
+static int sp8870_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct sp8870_state* state = fe->demodulator_priv;
 
        /*
@@ -479,7 +480,8 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
 
        for (trials = 1; trials <= MAXTRIALS; trials++) {
 
-               if ((err = sp8870_set_frontend_parameters(fe, p)))
+               err = sp8870_set_frontend_parameters(fe);
+               if (err)
                        return err;
 
                for (check_count = 0; check_count < MAXCHECKS; check_count++) {
@@ -579,10 +581,9 @@ error:
 }
 
 static struct dvb_frontend_ops sp8870_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Spase SP8870 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 470000000,
                .frequency_max          = 860000000,
                .frequency_stepsize     = 166666,
index 4a7c3d8426088bdccd39ab95b197b8b2963ab3d9..f4096ccb226e4b76146e001a4d78db1f52d7d756 100644 (file)
@@ -209,13 +209,13 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
        return 0;
 };
 
-static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
+static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
 {
        int known_parameters = 1;
 
        *reg0xc05 = 0x000;
 
-       switch (p->u.ofdm.constellation) {
+       switch (p->modulation) {
        case QPSK:
                break;
        case QAM_16:
@@ -231,7 +231,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
                return -EINVAL;
        };
 
-       switch (p->u.ofdm.hierarchy_information) {
+       switch (p->hierarchy) {
        case HIERARCHY_NONE:
                break;
        case HIERARCHY_1:
@@ -250,7 +250,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
                return -EINVAL;
        };
 
-       switch (p->u.ofdm.code_rate_HP) {
+       switch (p->code_rate_HP) {
        case FEC_1_2:
                break;
        case FEC_2_3:
@@ -303,17 +303,30 @@ static void divide (int n, int d, int *quotient_i, int *quotient_f)
 }
 
 static void sp887x_correct_offsets (struct sp887x_state* state,
-                                   struct dvb_frontend_parameters *p,
+                                   struct dtv_frontend_properties *p,
                                    int actual_freq)
 {
        static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
-       int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
+       int bw_index;
        int freq_offset = actual_freq - p->frequency;
        int sysclock = 61003; //[kHz]
        int ifreq = 36000000;
        int freq;
        int frequency_shift;
 
+       switch (p->bandwidth_hz) {
+       default:
+       case 8000000:
+               bw_index = 0;
+               break;
+       case 7000000:
+               bw_index = 1;
+               break;
+       case 6000000:
+               bw_index = 2;
+               break;
+       }
+
        if (p->inversion == INVERSION_ON)
                freq = ifreq - freq_offset;
        else
@@ -333,17 +346,17 @@ static void sp887x_correct_offsets (struct sp887x_state* state,
        sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
 }
 
-static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
-                                            struct dvb_frontend_parameters *p)
+static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct sp887x_state* state = fe->demodulator_priv;
        unsigned actual_freq;
        int err;
        u16 val, reg0xc05;
 
-       if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ &&
-           p->u.ofdm.bandwidth != BANDWIDTH_7_MHZ &&
-           p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ)
+       if (p->bandwidth_hz != 8000000 &&
+           p->bandwidth_hz != 7000000 &&
+           p->bandwidth_hz != 6000000)
                return -EINVAL;
 
        if ((err = configure_reg0xc05(p, &reg0xc05)))
@@ -353,7 +366,7 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
 
        /* setup the PLL */
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
        if (fe->ops.tuner_ops.get_frequency) {
@@ -369,9 +382,9 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
        sp887x_correct_offsets(state, p, actual_freq);
 
        /* filter for 6/7/8 Mhz channel */
-       if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+       if (p->bandwidth_hz == 6000000)
                val = 2;
-       else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+       else if (p->bandwidth_hz == 7000000)
                val = 1;
        else
                val = 0;
@@ -379,16 +392,16 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
        sp887x_writereg(state, 0x311, val);
 
        /* scan order: 2k first = 0, 8k first = 1 */
-       if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
+       if (p->transmission_mode == TRANSMISSION_MODE_2K)
                sp887x_writereg(state, 0x338, 0x000);
        else
                sp887x_writereg(state, 0x338, 0x001);
 
        sp887x_writereg(state, 0xc05, reg0xc05);
 
-       if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+       if (p->bandwidth_hz == 6000000)
                val = 2 << 3;
-       else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+       else if (p->bandwidth_hz == 7000000)
                val = 3 << 3;
        else
                val = 0 << 3;
@@ -579,10 +592,9 @@ error:
 }
 
 static struct dvb_frontend_ops sp887x_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "Spase SP887x DVB-T",
-               .type = FE_OFDM,
                .frequency_min =  50500000,
                .frequency_max = 858000000,
                .frequency_stepsize = 166666,
index 8408ef877b4be55e0e2e88bfc6c6ae6945024c63..38565beafe23a8594c22d8fbe5bc710fc74dd2f0 100644 (file)
@@ -1431,7 +1431,7 @@ static void stb0899_set_iterations(struct stb0899_state *state)
        stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
 }
 
-static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe)
 {
        struct stb0899_state *state = fe->demodulator_priv;
        struct stb0899_params *i_params = &state->params;
@@ -1441,8 +1441,8 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_fron
 
        u32 SearchRange, gain;
 
-       i_params->freq  = p->frequency;
-       i_params->srate = p->u.qpsk.symbol_rate;
+       i_params->freq  = props->frequency;
+       i_params->srate = props->symbol_rate;
        state->delsys = props->delivery_system;
        dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
 
@@ -1568,34 +1568,15 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_fron
 
        return DVBFE_ALGO_SEARCH_ERROR;
 }
-/*
- * stb0899_track
- * periodically check the signal level against a specified
- * threshold level and perform derotator centering.
- * called once we have a lock from a successful search
- * event.
- *
- * Will be called periodically called to maintain the
- * lock.
- *
- * Will be used to get parameters as well as info from
- * the decoded baseband header
- *
- * Once a new lock has established, the internal state
- * frequency (internal->freq) is updated
- */
-static int stb0899_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
-{
-       return 0;
-}
 
-static int stb0899_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stb0899_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stb0899_state *state             = fe->demodulator_priv;
        struct stb0899_internal *internal       = &state->internal;
 
        dprintk(state->verbose, FE_DEBUG, 1, "Get params");
-       p->u.qpsk.symbol_rate = internal->srate;
+       p->symbol_rate = internal->srate;
 
        return 0;
 }
@@ -1606,10 +1587,9 @@ static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops stb0899_ops = {
-
+       .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
        .info = {
                .name                   = "STB0899 Multistandard",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 0,
@@ -1632,8 +1612,7 @@ static struct dvb_frontend_ops stb0899_ops = {
 
        .get_frontend_algo              = stb0899_frontend_algo,
        .search                         = stb0899_search,
-       .track                          = stb0899_track,
-       .get_frontend                   = stb0899_get_frontend,
+       .get_frontend                   = stb0899_get_frontend,
 
 
        .read_status                    = stb0899_read_status,
index ed699647050e5eec49422391e98f660d7c9611cf..a0c3c526b132415d5bc705c2f5c8064e64fb9243 100644 (file)
@@ -75,9 +75,9 @@ static int stb6000_sleep(struct dvb_frontend *fe)
        return (ret == 1) ? 0 : ret;
 }
 
-static int stb6000_set_params(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *params)
+static int stb6000_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stb6000_priv *priv = fe->tuner_priv;
        unsigned int n, m;
        int ret;
@@ -93,8 +93,8 @@ static int stb6000_set_params(struct dvb_frontend *fe,
 
        dprintk("%s:\n", __func__);
 
-       freq_mhz = params->frequency / 1000;
-       bandwidth = params->u.qpsk.symbol_rate / 1000000;
+       freq_mhz = p->frequency / 1000;
+       bandwidth = p->symbol_rate / 1000000;
 
        if (bandwidth > 31)
                bandwidth = 31;
index bc1a8af4f6e105181670ee33ebe111f98425e0ff..def88abb30bf14b630f5110bf39732881159a2da 100644 (file)
@@ -327,7 +327,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
        int rc;
        const struct stb6100_lkup *ptr;
        struct stb6100_state *state = fe->tuner_priv;
-       struct dvb_frontend_parameters p;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
        u32 srate = 0, fvco, nint, nfrac;
        u8 regs[STB6100_NUMREGS];
@@ -337,9 +337,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
 
        if (fe->ops.get_frontend) {
                dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
-               fe->ops.get_frontend(fe, &p);
+               fe->ops.get_frontend(fe);
        }
-       srate = p.u.qpsk.symbol_rate;
+       srate = p->symbol_rate;
 
        /* Set up tuner cleanly, LPF calibration on */
        rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
index 0aa3962ff18bc37bb07d5e838fe43596405d9c20..fb5548a82208276281fdfe95e0d1206f8c9f18bd 100644 (file)
@@ -452,14 +452,7 @@ static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
        return 0;
 }
 
-static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
-       dprintk("%s(..)\n", __func__);
-       return 0;
-}
-
-static int stv0288_set_frontend(struct dvb_frontend *fe,
-                                       struct dvb_frontend_parameters *dfp)
+static int stv0288_set_frontend(struct dvb_frontend *fe)
 {
        struct stv0288_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -481,10 +474,8 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
                state->config->set_ts_params(fe, 0);
 
        /* only frequency & symbol_rate are used for tuner*/
-       dfp->frequency = c->frequency;
-       dfp->u.qpsk.symbol_rate = c->symbol_rate;
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, dfp);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -545,10 +536,9 @@ static void stv0288_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops stv0288_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "ST STV0288 DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 1000,  /* kHz for QPSK frontends */
@@ -578,7 +568,6 @@ static struct dvb_frontend_ops stv0288_ops = {
        .set_voltage = stv0288_set_voltage,
 
        .set_property = stv0288_set_property,
-       .get_property = stv0288_get_property,
        .set_frontend = stv0288_set_frontend,
 };
 
index 84d88f33275e060f690ffdf5b288d038431b561b..85c157a1fe5eec513623870e8424c4c4d197c280 100644 (file)
@@ -404,8 +404,9 @@ static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
        return 0;
 }
 
-static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stv0297_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0297_state *state = fe->demodulator_priv;
        int u_threshold;
        int initial_u;
@@ -417,7 +418,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        unsigned long timeout;
        fe_spectral_inversion_t inversion;
 
-       switch (p->u.qam.modulation) {
+       switch (p->modulation) {
        case QAM_16:
        case QAM_32:
        case QAM_64:
@@ -455,7 +456,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
 
        stv0297_init(fe);
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
@@ -519,16 +520,16 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
 
        /* set parameters */
-       stv0297_set_qam(state, p->u.qam.modulation);
-       stv0297_set_symbolrate(state, p->u.qam.symbol_rate / 1000);
-       stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
+       stv0297_set_qam(state, p->modulation);
+       stv0297_set_symbolrate(state, p->symbol_rate / 1000);
+       stv0297_set_sweeprate(state, sweeprate, p->symbol_rate / 1000);
        stv0297_set_carrieroffset(state, carrieroffset);
        stv0297_set_inversion(state, inversion);
 
        /* kick off lock */
        /* Disable corner detection for higher QAMs */
-       if (p->u.qam.modulation == QAM_128 ||
-               p->u.qam.modulation == QAM_256)
+       if (p->modulation == QAM_128 ||
+               p->modulation == QAM_256)
                stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
        else
                stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
@@ -613,8 +614,9 @@ timeout:
        return 0;
 }
 
-static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stv0297_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0297_state *state = fe->demodulator_priv;
        int reg_00, reg_83;
 
@@ -625,24 +627,24 @@ static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
        if (state->config->invert)
                p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
-       p->u.qam.symbol_rate = stv0297_get_symbolrate(state) * 1000;
-       p->u.qam.fec_inner = FEC_NONE;
+       p->symbol_rate = stv0297_get_symbolrate(state) * 1000;
+       p->fec_inner = FEC_NONE;
 
        switch ((reg_00 >> 4) & 0x7) {
        case 0:
-               p->u.qam.modulation = QAM_16;
+               p->modulation = QAM_16;
                break;
        case 1:
-               p->u.qam.modulation = QAM_32;
+               p->modulation = QAM_32;
                break;
        case 2:
-               p->u.qam.modulation = QAM_128;
+               p->modulation = QAM_128;
                break;
        case 3:
-               p->u.qam.modulation = QAM_256;
+               p->modulation = QAM_256;
                break;
        case 4:
-               p->u.qam.modulation = QAM_64;
+               p->modulation = QAM_64;
                break;
        }
 
@@ -688,10 +690,9 @@ error:
 }
 
 static struct dvb_frontend_ops stv0297_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A },
        .info = {
                 .name = "ST STV0297 DVB-C",
-                .type = FE_QAM,
                 .frequency_min = 47000000,
                 .frequency_max = 862000000,
                 .frequency_stepsize = 62500,
index 42684bec888374a6f8315a96b3b85b046947814d..057b5f8effc0dec16c24f3753329bf8ed354e8bb 100644 (file)
@@ -559,8 +559,9 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0299_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0299_state* state = fe->demodulator_priv;
        int invval = 0;
 
@@ -579,24 +580,25 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       stv0299_set_FEC (state, p->u.qpsk.fec_inner);
-       stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
+       stv0299_set_FEC(state, p->fec_inner);
+       stv0299_set_symbolrate(fe, p->symbol_rate);
        stv0299_writeregI(state, 0x22, 0x00);
        stv0299_writeregI(state, 0x23, 0x00);
 
        state->tuner_frequency = p->frequency;
-       state->fec_inner = p->u.qpsk.fec_inner;
-       state->symbol_rate = p->u.qpsk.symbol_rate;
+       state->fec_inner = p->fec_inner;
+       state->symbol_rate = p->symbol_rate;
 
        return 0;
 }
 
-static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0299_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0299_state* state = fe->demodulator_priv;
        s32 derot_freq;
        int invval;
@@ -614,8 +616,8 @@ static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        if (state->config->invert) invval = (~invval) & 1;
        p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
 
-       p->u.qpsk.fec_inner = stv0299_get_fec (state);
-       p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state);
+       p->fec_inner = stv0299_get_fec(state);
+       p->symbol_rate = stv0299_get_symbolrate(state);
 
        return 0;
 }
@@ -646,14 +648,15 @@ static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
        struct stv0299_state* state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 
        fesettings->min_delay_ms = state->config->min_delay_ms;
-       if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
-               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
+       if (p->symbol_rate < 10000000) {
+               fesettings->step_size = p->symbol_rate / 32000;
                fesettings->max_drift = 5000;
        } else {
-               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
-               fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
+               fesettings->step_size = p->symbol_rate / 16000;
+               fesettings->max_drift = p->symbol_rate / 2000;
        }
        return 0;
 }
@@ -705,10 +708,9 @@ error:
 }
 
 static struct dvb_frontend_ops stv0299_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "ST STV0299 DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 125,   /* kHz for QPSK frontends */
index e57ab53e2e27a7ad6bde437afdbdbc00a7278d85..fdd20c7737b57a968d4e5e8edf4d9900ef859d2b 100644 (file)
@@ -1577,9 +1577,9 @@ int stv0367ter_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int stv0367ter_algo(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *param)
+static int stv0367ter_algo(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367ter_state *ter_state = state->ter_state;
        int offset = 0, tempo = 0;
@@ -1591,7 +1591,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
 
        dprintk("%s:\n", __func__);
 
-       ter_state->frequency = param->frequency;
+       ter_state->frequency = p->frequency;
        ter_state->force = FE_TER_FORCENONE
                        + stv0367_readbits(state, F367TER_FORCE) * 2;
        ter_state->if_iq_mode = state->config->if_iq_mode;
@@ -1620,7 +1620,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
 
        usleep_range(5000, 7000);
 
-       switch (param->inversion) {
+       switch (p->inversion) {
        case INVERSION_AUTO:
        default:
                dprintk("%s: inversion AUTO\n", __func__);
@@ -1636,10 +1636,10 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
        case INVERSION_OFF:
                if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
                        stv0367_writebits(state, F367TER_IQ_INVERT,
-                                               param->inversion);
+                                               p->inversion);
                else
                        stv0367_writebits(state, F367TER_INV_SPECTR,
-                                               param->inversion);
+                                               p->inversion);
 
                break;
        }
@@ -1806,10 +1806,9 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
        return 0;
 }
 
-static int stv0367ter_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *param)
+static int stv0367ter_set_frontend(struct dvb_frontend *fe)
 {
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367ter_state *ter_state = state->ter_state;
 
@@ -1822,12 +1821,12 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
        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, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       switch (op->transmission_mode) {
+       switch (p->transmission_mode) {
        default:
        case TRANSMISSION_MODE_AUTO:
        case TRANSMISSION_MODE_2K:
@@ -1841,34 +1840,34 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
                break;
        }
 
-       switch (op->guard_interval) {
+       switch (p->guard_interval) {
        default:
        case GUARD_INTERVAL_1_32:
        case GUARD_INTERVAL_1_16:
        case GUARD_INTERVAL_1_8:
        case GUARD_INTERVAL_1_4:
-               ter_state->guard = op->guard_interval;
+               ter_state->guard = p->guard_interval;
                break;
        case GUARD_INTERVAL_AUTO:
                ter_state->guard = GUARD_INTERVAL_1_32;
                break;
        }
 
-       switch (op->bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (p->bandwidth_hz) {
+       case 6000000:
                ter_state->bw = FE_TER_CHAN_BW_6M;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                ter_state->bw = FE_TER_CHAN_BW_7M;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
        default:
                ter_state->bw = FE_TER_CHAN_BW_8M;
        }
 
        ter_state->hierarchy = FE_TER_HIER_NONE;
 
-       switch (param->inversion) {
+       switch (p->inversion) {
        case INVERSION_OFF:
        case INVERSION_ON:
                num_trials = 1;
@@ -1885,14 +1884,14 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
 
        while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) {
                if (!ter_state->first_lock) {
-                       if (param->inversion == INVERSION_AUTO)
+                       if (p->inversion == INVERSION_AUTO)
                                ter_state->sense = SenseTrials[index];
 
                }
-               stv0367ter_algo(fe,/* &pLook, result,*/ param);
+               stv0367ter_algo(fe);
 
                if ((ter_state->state == FE_TER_LOCKOK) &&
-                               (param->inversion == INVERSION_AUTO) &&
+                               (p->inversion == INVERSION_AUTO) &&
                                                                (index == 1)) {
                        /* invert spectrum sense */
                        SenseTrials[index] = SenseTrials[0];
@@ -1927,50 +1926,48 @@ static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
        return 0;
 }
 
-static int stv0367ter_get_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *param)
+static int stv0367ter_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367ter_state *ter_state = state->ter_state;
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
        int error = 0;
        enum stv0367_ter_mode mode;
        int constell = 0,/* snr = 0,*/ Data = 0;
 
-       param->frequency = stv0367_get_tuner_freq(fe);
-       if ((int)param->frequency < 0)
-               param->frequency = c->frequency;
+       p->frequency = stv0367_get_tuner_freq(fe);
+       if ((int)p->frequency < 0)
+               p->frequency = -p->frequency;
 
        constell = stv0367_readbits(state, F367TER_TPS_CONST);
        if (constell == 0)
-               op->constellation = QPSK;
+               p->modulation = QPSK;
        else if (constell == 1)
-               op->constellation = QAM_16;
+               p->modulation = QAM_16;
        else
-               op->constellation = QAM_64;
+               p->modulation = QAM_64;
 
-       param->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
+       p->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
 
        /* Get the Hierarchical mode */
        Data = stv0367_readbits(state, F367TER_TPS_HIERMODE);
 
        switch (Data) {
        case 0:
-               op->hierarchy_information = HIERARCHY_NONE;
+               p->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               op->hierarchy_information = HIERARCHY_1;
+               p->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               op->hierarchy_information = HIERARCHY_2;
+               p->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               op->hierarchy_information = HIERARCHY_4;
+               p->hierarchy = HIERARCHY_4;
                break;
        default:
-               op->hierarchy_information = HIERARCHY_AUTO;
+               p->hierarchy = HIERARCHY_AUTO;
                break; /* error */
        }
 
@@ -1982,22 +1979,22 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe,
 
        switch (Data) {
        case 0:
-               op->code_rate_HP = FEC_1_2;
+               p->code_rate_HP = FEC_1_2;
                break;
        case 1:
-               op->code_rate_HP = FEC_2_3;
+               p->code_rate_HP = FEC_2_3;
                break;
        case 2:
-               op->code_rate_HP = FEC_3_4;
+               p->code_rate_HP = FEC_3_4;
                break;
        case 3:
-               op->code_rate_HP = FEC_5_6;
+               p->code_rate_HP = FEC_5_6;
                break;
        case 4:
-               op->code_rate_HP = FEC_7_8;
+               p->code_rate_HP = FEC_7_8;
                break;
        default:
-               op->code_rate_HP = FEC_AUTO;
+               p->code_rate_HP = FEC_AUTO;
                break; /* error */
        }
 
@@ -2005,19 +2002,19 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe,
 
        switch (mode) {
        case FE_TER_MODE_2K:
-               op->transmission_mode = TRANSMISSION_MODE_2K;
+               p->transmission_mode = TRANSMISSION_MODE_2K;
                break;
 /*     case FE_TER_MODE_4K:
-               op->transmission_mode = TRANSMISSION_MODE_4K;
+               p->transmission_mode = TRANSMISSION_MODE_4K;
                break;*/
        case FE_TER_MODE_8K:
-               op->transmission_mode = TRANSMISSION_MODE_8K;
+               p->transmission_mode = TRANSMISSION_MODE_8K;
                break;
        default:
-               op->transmission_mode = TRANSMISSION_MODE_AUTO;
+               p->transmission_mode = TRANSMISSION_MODE_AUTO;
        }
 
-       op->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
+       p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
 
        return error;
 }
@@ -2265,9 +2262,9 @@ static void stv0367_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops stv0367ter_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "ST STV0367 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 47000000,
                .frequency_max          = 862000000,
                .frequency_stepsize     = 15625,
@@ -2822,9 +2819,8 @@ int stv0367cab_init(struct dvb_frontend *fe)
 }
 static
 enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
-                               struct dvb_frontend_parameters *param)
+                                            struct dtv_frontend_properties *p)
 {
-       struct dvb_qam_parameters *op = &param->u.qam;
        struct stv0367cab_state *cab_state = state->cab_state;
        enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC;
        u32     QAMFEC_Lock, QAM_Lock, u32_tmp,
@@ -2839,7 +2835,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
        /* A max lock time of 25 ms is allowed for delayed AGC */
        AGCTimeOut = 25;
        /* 100000 symbols needed by the TRL as a maximum value */
-       TRLTimeOut = 100000000 / op->symbol_rate;
+       TRLTimeOut = 100000000 / p->symbol_rate;
        /* CRLSymbols is the needed number of symbols to achieve a lock
           within [-4%, +4%] of the symbol rate.
           CRL timeout is calculated
@@ -2849,7 +2845,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
           A characterization must be performed
           with these echoes to get new timeout values.
        */
-       switch (op->modulation) {
+       switch (p->modulation) {
        case QAM_16:
                CRLSymbols = 150000;
                EQLTimeOut = 100;
@@ -2883,9 +2879,9 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
        } else
 #endif
        CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) /
-                                       (op->symbol_rate / 1000);
+                                       (p->symbol_rate / 1000);
 
-       CRLTimeOut = (1000 * CRLTimeOut) / op->symbol_rate;
+       CRLTimeOut = (1000 * CRLTimeOut) / p->symbol_rate;
        /* Timeouts below 50ms are coerced */
        if (CRLTimeOut < 50)
                CRLTimeOut = 50;
@@ -2915,7 +2911,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
        stv0367cab_set_derot_freq(state, cab_state->adc_clk,
                (1000 * (s32)state->config->if_khz + cab_state->derot_offset));
        /* Disable the Allpass Filter when the symbol rate is out of range */
-       if ((op->symbol_rate > 10800000) | (op->symbol_rate < 1800000)) {
+       if ((p->symbol_rate > 10800000) | (p->symbol_rate < 1800000)) {
                stv0367_writebits(state, F367CAB_ADJ_EN, 0);
                stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
        }
@@ -2999,7 +2995,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
 
        if (QAMFEC_Lock) {
                signalType = FE_CAB_DATAOK;
-               cab_state->modulation = op->modulation;
+               cab_state->modulation = p->modulation;
                cab_state->spect_inv = stv0367_readbits(state,
                                                        F367CAB_QUAD_INV);
 #if 0
@@ -3081,20 +3077,19 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
        return signalType;
 }
 
-static int stv0367cab_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *param)
+static int stv0367cab_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367cab_state *cab_state = state->cab_state;
-       struct dvb_qam_parameters *op = &param->u.qam;
        enum stv0367cab_mod QAMSize = 0;
 
        dprintk("%s: freq = %d, srate = %d\n", __func__,
-                                       param->frequency, op->symbol_rate);
+                                       p->frequency, p->symbol_rate);
 
        cab_state->derot_offset = 0;
 
-       switch (op->modulation) {
+       switch (p->modulation) {
        case QAM_16:
                QAMSize = FE_CAB_MOD_QAM16;
                break;
@@ -3120,77 +3115,76 @@ static int stv0367cab_set_frontend(struct dvb_frontend *fe,
        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, param);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        stv0367cab_SetQamSize(
                        state,
-                       op->symbol_rate,
+                       p->symbol_rate,
                        QAMSize);
 
        stv0367cab_set_srate(state,
                        cab_state->adc_clk,
                        cab_state->mclk,
-                       op->symbol_rate,
+                       p->symbol_rate,
                        QAMSize);
        /* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */
-       cab_state->state = stv0367cab_algo(state, param);
+       cab_state->state = stv0367cab_algo(state, p);
        return 0;
 }
 
-static int stv0367cab_get_frontend(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *param)
+static int stv0367cab_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0367_state *state = fe->demodulator_priv;
        struct stv0367cab_state *cab_state = state->cab_state;
-       struct dvb_qam_parameters *op = &param->u.qam;
 
        enum stv0367cab_mod QAMSize;
 
        dprintk("%s:\n", __func__);
 
-       op->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
+       p->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
 
        QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
        switch (QAMSize) {
        case FE_CAB_MOD_QAM16:
-               op->modulation = QAM_16;
+               p->modulation = QAM_16;
                break;
        case FE_CAB_MOD_QAM32:
-               op->modulation = QAM_32;
+               p->modulation = QAM_32;
                break;
        case FE_CAB_MOD_QAM64:
-               op->modulation = QAM_64;
+               p->modulation = QAM_64;
                break;
        case FE_CAB_MOD_QAM128:
-               op->modulation = QAM_128;
+               p->modulation = QAM_128;
                break;
        case QAM_256:
-               op->modulation = QAM_256;
+               p->modulation = QAM_256;
                break;
        default:
                break;
        }
 
-       param->frequency = stv0367_get_tuner_freq(fe);
+       p->frequency = stv0367_get_tuner_freq(fe);
 
-       dprintk("%s: tuner frequency = %d\n", __func__, param->frequency);
+       dprintk("%s: tuner frequency = %d\n", __func__, p->frequency);
 
        if (state->config->if_khz == 0) {
-               param->frequency +=
+               p->frequency +=
                        (stv0367cab_get_derot_freq(state, cab_state->adc_clk) -
                        cab_state->adc_clk / 4000);
                return 0;
        }
 
        if (state->config->if_khz > cab_state->adc_clk / 1000)
-               param->frequency += (state->config->if_khz
+               p->frequency += (state->config->if_khz
                        - stv0367cab_get_derot_freq(state, cab_state->adc_clk)
                        - cab_state->adc_clk / 1000);
        else
-               param->frequency += (state->config->if_khz
+               p->frequency += (state->config->if_khz
                        - stv0367cab_get_derot_freq(state, cab_state->adc_clk));
 
        return 0;
@@ -3386,9 +3380,9 @@ static int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks)
 };
 
 static struct dvb_frontend_ops stv0367cab_ops = {
+       .delsys = { SYS_DVBC_ANNEX_A },
        .info = {
                .name = "ST STV0367 DVB-C",
-               .type = FE_QAM,
                .frequency_min = 47000000,
                .frequency_max = 862000000,
                .frequency_stepsize = 62500,
index 0ca316d6fffacf68733df21fe3e5419149b8ea0f..7f1badaf0d03044b2c2e4779ed746e2d03bbae0c 100644 (file)
@@ -973,22 +973,6 @@ static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe)
        return DVBFE_ALGO_CUSTOM;
 }
 
-static int stb0900_set_property(struct dvb_frontend *fe,
-                               struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-
-       return 0;
-}
-
-static int stb0900_get_property(struct dvb_frontend *fe,
-                               struct dtv_property *tvp)
-{
-       dprintk("%s(..)\n", __func__);
-
-       return 0;
-}
-
 void stv0900_start_search(struct stv0900_internal *intp,
                                enum fe_stv0900_demod_num demod)
 {
@@ -1574,8 +1558,7 @@ static int stv0900_status(struct stv0900_internal *intp,
        return locked;
 }
 
-static enum dvbfe_search stv0900_search(struct dvb_frontend *fe,
-                                       struct dvb_frontend_parameters *params)
+static enum dvbfe_search stv0900_search(struct dvb_frontend *fe)
 {
        struct stv0900_state *state = fe->demodulator_priv;
        struct stv0900_internal *intp = state->internal;
@@ -1675,12 +1658,6 @@ static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status)
        return 0;
 }
 
-static int stv0900_track(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *p)
-{
-       return 0;
-}
-
 static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts)
 {
 
@@ -1866,24 +1843,23 @@ static int stv0900_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int stv0900_get_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int stv0900_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct stv0900_state *state = fe->demodulator_priv;
        struct stv0900_internal *intp = state->internal;
        enum fe_stv0900_demod_num demod = state->demod;
        struct stv0900_signal_info p_result = intp->result[demod];
 
        p->frequency = p_result.locked ? p_result.frequency : 0;
-       p->u.qpsk.symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
+       p->symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
        return 0;
 }
 
 static struct dvb_frontend_ops stv0900_ops = {
-
+       .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
        .info = {
                .name                   = "STV0900 frontend",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 125,
@@ -1907,10 +1883,7 @@ static struct dvb_frontend_ops stv0900_ops = {
        .diseqc_send_burst              = stv0900_send_burst,
        .diseqc_recv_slave_reply        = stv0900_recv_slave_reply,
        .set_tone                       = stv0900_set_tone,
-       .set_property                   = stb0900_set_property,
-       .get_property                   = stb0900_get_property,
        .search                         = stv0900_search,
-       .track                          = stv0900_track,
        .read_status                    = stv0900_read_status,
        .read_ber                       = stv0900_read_ber,
        .read_signal_strength           = stv0900_read_signal_strength,
index ebda41936b9094b3cc3259231337c507dd474360..4aef1877ed422deb38d9dd4f53658f7601b1afdc 100644 (file)
@@ -3427,17 +3427,17 @@ err:
        return -1;
 }
 
-static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
 {
        struct stv090x_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *props = &fe->dtv_property_cache;
 
-       if (p->frequency == 0)
+       if (props->frequency == 0)
                return DVBFE_ALGO_SEARCH_INVALID;
 
        state->delsys = props->delivery_system;
-       state->frequency = p->frequency;
-       state->srate = p->u.qpsk.symbol_rate;
+       state->frequency = props->frequency;
+       state->srate = props->symbol_rate;
        state->search_mode = STV090x_SEARCH_AUTO;
        state->algo = STV090x_COLD_SEARCH;
        state->fec = STV090x_PRERR;
@@ -4712,10 +4712,9 @@ int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
 EXPORT_SYMBOL(stv090x_set_gpio);
 
 static struct dvb_frontend_ops stv090x_ops = {
-
+       .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
        .info = {
                .name                   = "STV090x Multistandard",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 0,
@@ -4743,7 +4742,7 @@ static struct dvb_frontend_ops stv090x_ops = {
        .read_status                    = stv090x_read_status,
        .read_ber                       = stv090x_read_per,
        .read_signal_strength           = stv090x_read_signal_strength,
-       .read_snr                       = stv090x_read_cnr
+       .read_snr                       = stv090x_read_cnr,
 };
 
 
index 2dca7c8e5148bb989b1e75b7ec5605afdf72851d..20b5fa92c53e7374977b55800ec95c831239966c 100644 (file)
@@ -347,8 +347,7 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
        return 0;
 }
 
-static int stv6110_set_params(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *params)
+static int stv6110_set_params(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 bandwidth = carrier_width(c->symbol_rate, c->rolloff);
index 6ca533ea0f0ec047258a568335b7fa17e3762b96..1bff7f457e196257136fa71a2790010d5ec370bb 100644 (file)
@@ -224,47 +224,86 @@ static int tda10021_init (struct dvb_frontend *fe)
        return 0;
 }
 
-static int tda10021_set_parameters (struct dvb_frontend *fe,
-                           struct dvb_frontend_parameters *p)
+struct qam_params {
+       u8 conf, agcref, lthr, mseth, aref;
+};
+
+static int tda10021_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys  = c->delivery_system;
+       unsigned qam = c->modulation;
+       bool is_annex_c;
+       u32 reg0x3d;
        struct tda10021_state* state = fe->demodulator_priv;
+       static const struct qam_params qam_params[] = {
+               /* Modulation  Conf  AGCref  LTHR  MSETH  AREF */
+               [QPSK]     = { 0x14, 0x78,   0x78, 0x8c,  0x96 },
+               [QAM_16]   = { 0x00, 0x8c,   0x87, 0xa2,  0x91 },
+               [QAM_32]   = { 0x04, 0x8c,   0x64, 0x74,  0x96 },
+               [QAM_64]   = { 0x08, 0x6a,   0x46, 0x43,  0x6a },
+               [QAM_128]  = { 0x0c, 0x78,   0x36, 0x34,  0x7e },
+               [QAM_256]  = { 0x10, 0x5c,   0x26, 0x23,  0x6b },
+       };
+
+       switch (delsys) {
+       case SYS_DVBC_ANNEX_A:
+               is_annex_c = false;
+               break;
+       case SYS_DVBC_ANNEX_C:
+               is_annex_c = true;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       //table for QAM4-QAM256 ready  QAM4  QAM16 QAM32 QAM64 QAM128 QAM256
-       //CONF
-       static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c,  0x10 };
-       //AGCREF value
-       static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78,  0x5c };
-       //LTHR value
-       static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36,  0x26 };
-       //MSETH
-       static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34,  0x23 };
-       //AREF
-       static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e,  0x6b };
-
-       int qam = p->u.qam.modulation;
-
-       if (qam < 0 || qam > 5)
+       /*
+        * gcc optimizes the code bellow the same way as it would code:
+        *           "if (qam > 5) return -EINVAL;"
+        * Yet, the code is clearer, as it shows what QAM standards are
+        * supported by the driver, and avoids the usage of magic numbers on
+        * it.
+        */
+       switch (qam) {
+       case QPSK:
+       case QAM_16:
+       case QAM_32:
+       case QAM_64:
+       case QAM_128:
+       case QAM_256:
+               break;
+       default:
                return -EINVAL;
+       }
 
-       if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF)
+       if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
                return -EINVAL;
 
-       //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
+       /*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
-       _tda10021_writereg (state, 0x34, state->pwm);
-
-       _tda10021_writereg (state, 0x01, reg0x01[qam]);
-       _tda10021_writereg (state, 0x05, reg0x05[qam]);
-       _tda10021_writereg (state, 0x08, reg0x08[qam]);
-       _tda10021_writereg (state, 0x09, reg0x09[qam]);
-
-       tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
+       tda10021_set_symbolrate(state, c->symbol_rate);
+       _tda10021_writereg(state, 0x34, state->pwm);
+
+       _tda10021_writereg(state, 0x01, qam_params[qam].agcref);
+       _tda10021_writereg(state, 0x05, qam_params[qam].lthr);
+       _tda10021_writereg(state, 0x08, qam_params[qam].mseth);
+       _tda10021_writereg(state, 0x09, qam_params[qam].aref);
+
+       /*
+        * Bit 0 == 0 means roll-off = 0.15 (Annex A)
+        *       == 1 means roll-off = 0.13 (Annex C)
+        */
+       reg0x3d = tda10021_readreg (state, 0x3d);
+       if (is_annex_c)
+               _tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
+       else
+               _tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
+       tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
 
        return 0;
 }
@@ -347,8 +386,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda10021_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda10021_state* state = fe->demodulator_priv;
        int sync;
        s8 afc = 0;
@@ -360,17 +400,17 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
                printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
                                  "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
                        state->frontend.dvb->num, afc,
-                      -((s32)p->u.qam.symbol_rate * afc) >> 10);
+                      -((s32)p->symbol_rate * afc) >> 10);
        }
 
        p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
-       p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+       p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
 
-       p->u.qam.fec_inner = FEC_NONE;
+       p->fec_inner = FEC_NONE;
        p->frequency = ((p->frequency + 31250) / 62500) * 62500;
 
        if (sync & 2)
-               p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
+               p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
 
        return 0;
 }
@@ -444,10 +484,9 @@ error:
 }
 
 static struct dvb_frontend_ops tda10021_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
        .info = {
                .name = "Philips TDA10021 DVB-C",
-               .type = FE_QAM,
                .frequency_stepsize = 62500,
                .frequency_min = 47000000,
                .frequency_max = 862000000,
index a3c34eecdee9a81315bf68b44c5d6f23923c5cda..ca1e0d54b69afcf343221120f7cb6636962a10d6 100644 (file)
@@ -298,42 +298,80 @@ static int tda10023_init (struct dvb_frontend *fe)
        return 0;
 }
 
-static int tda10023_set_parameters (struct dvb_frontend *fe,
-                           struct dvb_frontend_parameters *p)
+struct qam_params {
+       u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd;
+};
+
+static int tda10023_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u32 delsys  = c->delivery_system;
+       unsigned qam = c->modulation;
+       bool is_annex_c;
        struct tda10023_state* state = fe->demodulator_priv;
-
-       static int qamvals[6][6] = {
-               //  QAM   LOCKTHR  MSETH   AREF AGCREFNYQ  ERAGCNYQ_THD
-               { (5<<2),  0x78,    0x8c,   0x96,   0x78,   0x4c  },  // 4 QAM
-               { (0<<2),  0x87,    0xa2,   0x91,   0x8c,   0x57  },  // 16 QAM
-               { (1<<2),  0x64,    0x74,   0x96,   0x8c,   0x57  },  // 32 QAM
-               { (2<<2),  0x46,    0x43,   0x6a,   0x6a,   0x44  },  // 64 QAM
-               { (3<<2),  0x36,    0x34,   0x7e,   0x78,   0x4c  },  // 128 QAM
-               { (4<<2),  0x26,    0x23,   0x6c,   0x5c,   0x3c  },  // 256 QAM
+       static const struct qam_params qam_params[] = {
+               /* Modulation  QAM    LOCKTHR   MSETH   AREF AGCREFNYQ ERAGCNYQ_THD */
+               [QPSK]    = { (5<<2),  0x78,    0x8c,   0x96,   0x78,   0x4c  },
+               [QAM_16]  = { (0<<2),  0x87,    0xa2,   0x91,   0x8c,   0x57  },
+               [QAM_32]  = { (1<<2),  0x64,    0x74,   0x96,   0x8c,   0x57  },
+               [QAM_64]  = { (2<<2),  0x46,    0x43,   0x6a,   0x6a,   0x44  },
+               [QAM_128] = { (3<<2),  0x36,    0x34,   0x7e,   0x78,   0x4c  },
+               [QAM_256] = { (4<<2),  0x26,    0x23,   0x6c,   0x5c,   0x3c  },
        };
 
-       int qam = p->u.qam.modulation;
+       switch (delsys) {
+       case SYS_DVBC_ANNEX_A:
+               is_annex_c = false;
+               break;
+       case SYS_DVBC_ANNEX_C:
+               is_annex_c = true;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       if (qam < 0 || qam > 5)
+       /*
+        * gcc optimizes the code bellow the same way as it would code:
+        *               "if (qam > 5) return -EINVAL;"
+        * Yet, the code is clearer, as it shows what QAM standards are
+        * supported by the driver, and avoids the usage of magic numbers on
+        * it.
+        */
+       switch (qam) {
+       case QPSK:
+       case QAM_16:
+       case QAM_32:
+       case QAM_64:
+       case QAM_128:
+       case QAM_256:
+               break;
+       default:
                return -EINVAL;
+       }
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       tda10023_set_symbolrate (state, p->u.qam.symbol_rate);
-       tda10023_writereg (state, 0x05, qamvals[qam][1]);
-       tda10023_writereg (state, 0x08, qamvals[qam][2]);
-       tda10023_writereg (state, 0x09, qamvals[qam][3]);
-       tda10023_writereg (state, 0xb4, qamvals[qam][4]);
-       tda10023_writereg (state, 0xb6, qamvals[qam][5]);
-
-//     tda10023_writereg (state, 0x04, (p->inversion?0x12:0x32));
-//     tda10023_writebit (state, 0x04, 0x60, (p->inversion?0:0x20));
-       tda10023_writebit (state, 0x04, 0x40, 0x40);
-       tda10023_setup_reg0 (state, qamvals[qam][0]);
+       tda10023_set_symbolrate(state, c->symbol_rate);
+       tda10023_writereg(state, 0x05, qam_params[qam].lockthr);
+       tda10023_writereg(state, 0x08, qam_params[qam].mseth);
+       tda10023_writereg(state, 0x09, qam_params[qam].aref);
+       tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq);
+       tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd);
+#if 0
+       tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32));
+       tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20));
+#endif
+       tda10023_writebit(state, 0x04, 0x40, 0x40);
+
+       if (is_annex_c)
+               tda10023_writebit(state, 0x3d, 0xfc, 0x03);
+       else
+               tda10023_writebit(state, 0x3d, 0xfc, 0x02);
+
+       tda10023_setup_reg0(state, qam_params[qam].qam);
 
        return 0;
 }
@@ -418,8 +456,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda10023_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda10023_state* state = fe->demodulator_priv;
        int sync,inv;
        s8 afc = 0;
@@ -433,17 +472,17 @@ static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
                printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" :
                                  "DVB: TDA10023(%d): [AFC (%d) %dHz]\n",
                        state->frontend.dvb->num, afc,
-                      -((s32)p->u.qam.symbol_rate * afc) >> 10);
+                      -((s32)p->symbol_rate * afc) >> 10);
        }
 
        p->inversion = (inv&0x20?0:1);
-       p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+       p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
 
-       p->u.qam.fec_inner = FEC_NONE;
+       p->fec_inner = FEC_NONE;
        p->frequency = ((p->frequency + 31250) / 62500) * 62500;
 
        if (sync & 2)
-               p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
+               p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
 
        return 0;
 }
@@ -534,10 +573,9 @@ error:
 }
 
 static struct dvb_frontend_ops tda10023_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
        .info = {
                .name = "Philips TDA10023 DVB-C",
-               .type = FE_QAM,
                .frequency_stepsize = 62500,
                .frequency_min =  47000000,
                .frequency_max = 862000000,
@@ -557,7 +595,6 @@ static struct dvb_frontend_ops tda10023_ops = {
 
        .set_frontend = tda10023_set_parameters,
        .get_frontend = tda10023_get_frontend,
-
        .read_status = tda10023_read_status,
        .read_ber = tda10023_read_ber,
        .read_signal_strength = tda10023_read_signal_strength,
index 7f105946a4342171056e8b774c7032ec4970dedc..71fb63299de78414d003f507ebca09f2a2b86bb5 100644 (file)
@@ -153,7 +153,7 @@ struct tda10048_state {
        u32 pll_pfactor;
        u32 sample_freq;
 
-       enum fe_bandwidth bandwidth;
+       u32 bandwidth;
 };
 
 static struct init_tab {
@@ -341,21 +341,14 @@ static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
 {
        struct tda10048_state *state = fe->demodulator_priv;
        u64 t, z;
-       u32 b = 8000000;
 
        dprintk(1, "%s()\n", __func__);
 
        if (sample_freq_hz == 0)
                return -EINVAL;
 
-       if (bw == BANDWIDTH_6_MHZ)
-               b = 6000000;
-       else
-       if (bw == BANDWIDTH_7_MHZ)
-               b = 7000000;
-
        /* WREF = (B / (7 * fs)) * 2^31 */
-       t = b * 10;
+       t = bw * 10;
        /* avoid warning: this decimal constant is unsigned only in ISO C90 */
        /* t *= 2147483648 on 32bit platforms */
        t *= (2048 * 1024);
@@ -378,25 +371,18 @@ static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
 {
        struct tda10048_state *state = fe->demodulator_priv;
        u64 t;
-       u32 b = 8000000;
 
        dprintk(1, "%s()\n", __func__);
 
        if (sample_freq_hz == 0)
                return -EINVAL;
 
-       if (bw == BANDWIDTH_6_MHZ)
-               b = 6000000;
-       else
-       if (bw == BANDWIDTH_7_MHZ)
-               b = 7000000;
-
        /* INVWREF = ((7 * fs) / B) * 2^5 */
        t = sample_freq_hz;
        t *= 7;
        t *= 32;
        t *= 10;
-       do_div(t, b);
+       do_div(t, bw);
        t += 5;
        do_div(t, 10);
 
@@ -407,16 +393,16 @@ static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
 }
 
 static int tda10048_set_bandwidth(struct dvb_frontend *fe,
-       enum fe_bandwidth bw)
+       u32 bw)
 {
        struct tda10048_state *state = fe->demodulator_priv;
        dprintk(1, "%s(bw=%d)\n", __func__, bw);
 
        /* Bandwidth setting may need to be adjusted */
        switch (bw) {
-       case BANDWIDTH_6_MHZ:
-       case BANDWIDTH_7_MHZ:
-       case BANDWIDTH_8_MHZ:
+       case 6000000:
+       case 7000000:
+       case 8000000:
                tda10048_set_wref(fe, state->sample_freq, bw);
                tda10048_set_invwref(fe, state->sample_freq, bw);
                break;
@@ -430,7 +416,7 @@ static int tda10048_set_bandwidth(struct dvb_frontend *fe,
        return 0;
 }
 
-static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
+static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
 {
        struct tda10048_state *state = fe->demodulator_priv;
        struct tda10048_config *config = &state->config;
@@ -441,13 +427,13 @@ static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
 
        /* based on target bandwidth and clk we calculate pll factors */
        switch (bw) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                if_freq_khz = config->dtv6_if_freq_khz;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                if_freq_khz = config->dtv7_if_freq_khz;
                break;
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                if_freq_khz = config->dtv8_if_freq_khz;
                break;
        default:
@@ -601,7 +587,7 @@ static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
 
 /* Retrieve the demod settings */
 static int tda10048_get_tps(struct tda10048_state *state,
-       struct dvb_ofdm_parameters *p)
+       struct dtv_frontend_properties *p)
 {
        u8 val;
 
@@ -612,27 +598,27 @@ static int tda10048_get_tps(struct tda10048_state *state,
        val = tda10048_readreg(state, TDA10048_OUT_CONF2);
        switch ((val & 0x60) >> 5) {
        case 0:
-               p->constellation = QPSK;
+               p->modulation = QPSK;
                break;
        case 1:
-               p->constellation = QAM_16;
+               p->modulation = QAM_16;
                break;
        case 2:
-               p->constellation = QAM_64;
+               p->modulation = QAM_64;
                break;
        }
        switch ((val & 0x18) >> 3) {
        case 0:
-               p->hierarchy_information = HIERARCHY_NONE;
+               p->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               p->hierarchy_information = HIERARCHY_1;
+               p->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               p->hierarchy_information = HIERARCHY_2;
+               p->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               p->hierarchy_information = HIERARCHY_4;
+               p->hierarchy = HIERARCHY_4;
                break;
        }
        switch (val & 0x07) {
@@ -738,17 +724,17 @@ static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
 
 /* 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)
+static int tda10048_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda10048_state *state = fe->demodulator_priv;
 
        dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
 
        /* Update the I/F pll's if the bandwidth changes */
-       if (p->u.ofdm.bandwidth != state->bandwidth) {
-               tda10048_set_if(fe, p->u.ofdm.bandwidth);
-               tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth);
+       if (p->bandwidth_hz != state->bandwidth) {
+               tda10048_set_if(fe, p->bandwidth_hz);
+               tda10048_set_bandwidth(fe, p->bandwidth_hz);
        }
 
        if (fe->ops.tuner_ops.set_params) {
@@ -756,7 +742,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 1);
 
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
 
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
@@ -797,8 +783,8 @@ static int tda10048_init(struct dvb_frontend *fe)
        tda10048_set_inversion(fe, config->inversion);
 
        /* Establish default RF values */
-       tda10048_set_if(fe, BANDWIDTH_8_MHZ);
-       tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ);
+       tda10048_set_if(fe, 8000000);
+       tda10048_set_bandwidth(fe, 8000000);
 
        /* Ensure we leave the gate closed */
        tda10048_i2c_gate_ctrl(fe, 0);
@@ -1042,9 +1028,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
        return 0;
 }
 
-static int tda10048_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int tda10048_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda10048_state *state = fe->demodulator_priv;
 
        dprintk(1, "%s()\n", __func__);
@@ -1052,7 +1038,7 @@ static int tda10048_get_frontend(struct dvb_frontend *fe,
        p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
                & 0x20 ? INVERSION_ON : INVERSION_OFF;
 
-       return tda10048_get_tps(state, &p->u.ofdm);
+       return tda10048_get_tps(state, p);
 }
 
 static int tda10048_get_tune_settings(struct dvb_frontend *fe,
@@ -1126,7 +1112,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
        memcpy(&state->config, config, sizeof(*config));
        state->i2c = i2c;
        state->fwloaded = config->no_firmware;
-       state->bandwidth = BANDWIDTH_8_MHZ;
+       state->bandwidth = 8000000;
 
        /* check if the demod is present */
        if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
@@ -1152,11 +1138,11 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
        tda10048_establish_defaults(&state->frontend);
 
        /* Set the xtal and freq defaults */
-       if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+       if (tda10048_set_if(&state->frontend, 8000000) != 0)
                goto error;
 
        /* Default bandwidth */
-       if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+       if (tda10048_set_bandwidth(&state->frontend, 8000000) != 0)
                goto error;
 
        /* Leave the gate closed */
@@ -1171,10 +1157,9 @@ error:
 EXPORT_SYMBOL(tda10048_attach);
 
 static struct dvb_frontend_ops tda10048_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "NXP TDA10048HN DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 177000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 166666,
index ea485d9235508c4053ff64c76125af960c8b6daf..ae6f22aae677e3e0a88988233f380e47e249f47d 100644 (file)
@@ -224,22 +224,22 @@ static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
 }
 
 static int tda10045h_set_bandwidth(struct tda1004x_state *state,
-                                  fe_bandwidth_t bandwidth)
+                                  u32 bandwidth)
 {
        static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
        static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
        static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
 
        switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
                break;
 
@@ -253,7 +253,7 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
 }
 
 static int tda10046h_set_bandwidth(struct tda1004x_state *state,
-                                  fe_bandwidth_t bandwidth)
+                                  u32 bandwidth)
 {
        static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
        static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
@@ -270,7 +270,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
        else
                tda10046_clk53m = 1;
        switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                if (tda10046_clk53m)
                        tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
                                                  sizeof(bandwidth_6mhz_53M));
@@ -283,7 +283,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
                }
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                if (tda10046_clk53m)
                        tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
                                                  sizeof(bandwidth_7mhz_53M));
@@ -296,7 +296,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
                }
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                if (tda10046_clk53m)
                        tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
                                                  sizeof(bandwidth_8mhz_53M));
@@ -409,7 +409,7 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
        msleep(10);
 
        /* set parameters */
-       tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ);
+       tda10045h_set_bandwidth(state, 8000000);
 
        ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
        release_firmware(fw);
@@ -473,7 +473,7 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
                tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
                break;
        }
-       tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
+       tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */
        /* let the PLLs settle */
        msleep(120);
 }
@@ -697,9 +697,9 @@ static int tda10046_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int tda1004x_set_fe(struct dvb_frontend* fe,
-                          struct dvb_frontend_parameters *fe_params)
+static int tda1004x_set_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
        struct tda1004x_state* state = fe->demodulator_priv;
        int tmp;
        int inversion;
@@ -718,7 +718,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
 
        // set frequency
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, fe_params);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
@@ -726,37 +726,37 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        // Hardcoded to use auto as much as possible on the TDA10045 as it
        // is very unreliable if AUTO mode is _not_ used.
        if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
-               fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
-               fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
-               fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+               fe_params->code_rate_HP = FEC_AUTO;
+               fe_params->guard_interval = GUARD_INTERVAL_AUTO;
+               fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
        }
 
        // Set standard params.. or put them to auto
-       if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
-               (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
-               (fe_params->u.ofdm.constellation == QAM_AUTO) ||
-               (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+       if ((fe_params->code_rate_HP == FEC_AUTO) ||
+               (fe_params->code_rate_LP == FEC_AUTO) ||
+               (fe_params->modulation == QAM_AUTO) ||
+               (fe_params->hierarchy == HIERARCHY_AUTO)) {
                tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1);        // enable auto
-               tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
+               tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); /* turn off modulation bits */
                tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
                tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits
        } else {
                tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0);        // disable auto
 
                // set HP FEC
-               tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP);
+               tmp = tda1004x_encode_fec(fe_params->code_rate_HP);
                if (tmp < 0)
                        return tmp;
                tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
 
                // set LP FEC
-               tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP);
+               tmp = tda1004x_encode_fec(fe_params->code_rate_LP);
                if (tmp < 0)
                        return tmp;
                tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
 
-               // set constellation
-               switch (fe_params->u.ofdm.constellation) {
+               /* set modulation */
+               switch (fe_params->modulation) {
                case QPSK:
                        tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0);
                        break;
@@ -774,7 +774,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
                }
 
                // set hierarchy
-               switch (fe_params->u.ofdm.hierarchy_information) {
+               switch (fe_params->hierarchy) {
                case HIERARCHY_NONE:
                        tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
                        break;
@@ -799,11 +799,11 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        // set bandwidth
        switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
-               tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
+               tda10045h_set_bandwidth(state, fe_params->bandwidth_hz);
                break;
 
        case TDA1004X_DEMOD_TDA10046:
-               tda10046h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
+               tda10046h_set_bandwidth(state, fe_params->bandwidth_hz);
                break;
        }
 
@@ -825,7 +825,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        }
 
        // set guard interval
-       switch (fe_params->u.ofdm.guard_interval) {
+       switch (fe_params->guard_interval) {
        case GUARD_INTERVAL_1_32:
                tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
                tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
@@ -856,7 +856,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        }
 
        // set transmission mode
-       switch (fe_params->u.ofdm.transmission_mode) {
+       switch (fe_params->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
                tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
@@ -895,8 +895,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        return 0;
 }
 
-static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+static int tda1004x_get_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
        struct tda1004x_state* state = fe->demodulator_priv;
 
        dprintk("%s\n", __func__);
@@ -913,13 +914,13 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
        case TDA1004X_DEMOD_TDA10045:
                switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
                case 0x14:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+                       fe_params->bandwidth_hz = 8000000;
                        break;
                case 0xdb:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+                       fe_params->bandwidth_hz = 7000000;
                        break;
                case 0x4f:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+                       fe_params->bandwidth_hz = 6000000;
                        break;
                }
                break;
@@ -927,73 +928,73 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
                switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
                case 0x5c:
                case 0x54:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+                       fe_params->bandwidth_hz = 8000000;
                        break;
                case 0x6a:
                case 0x60:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+                       fe_params->bandwidth_hz = 7000000;
                        break;
                case 0x7b:
                case 0x70:
-                       fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+                       fe_params->bandwidth_hz = 6000000;
                        break;
                }
                break;
        }
 
        // FEC
-       fe_params->u.ofdm.code_rate_HP =
+       fe_params->code_rate_HP =
            tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);
-       fe_params->u.ofdm.code_rate_LP =
+       fe_params->code_rate_LP =
            tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);
 
-       // constellation
+       /* modulation */
        switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {
        case 0:
-               fe_params->u.ofdm.constellation = QPSK;
+               fe_params->modulation = QPSK;
                break;
        case 1:
-               fe_params->u.ofdm.constellation = QAM_16;
+               fe_params->modulation = QAM_16;
                break;
        case 2:
-               fe_params->u.ofdm.constellation = QAM_64;
+               fe_params->modulation = QAM_64;
                break;
        }
 
        // transmission mode
-       fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+       fe_params->transmission_mode = TRANSMISSION_MODE_2K;
        if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
-               fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               fe_params->transmission_mode = TRANSMISSION_MODE_8K;
 
        // guard interval
        switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
        case 0:
-               fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               fe_params->guard_interval = GUARD_INTERVAL_1_32;
                break;
        case 1:
-               fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               fe_params->guard_interval = GUARD_INTERVAL_1_16;
                break;
        case 2:
-               fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               fe_params->guard_interval = GUARD_INTERVAL_1_8;
                break;
        case 3:
-               fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               fe_params->guard_interval = GUARD_INTERVAL_1_4;
                break;
        }
 
        // hierarchy
        switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
        case 0:
-               fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               fe_params->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               fe_params->u.ofdm.hierarchy_information = HIERARCHY_1;
+               fe_params->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               fe_params->u.ofdm.hierarchy_information = HIERARCHY_2;
+               fe_params->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               fe_params->u.ofdm.hierarchy_information = HIERARCHY_4;
+               fe_params->hierarchy = HIERARCHY_4;
                break;
        }
 
@@ -1231,9 +1232,9 @@ static void tda1004x_release(struct dvb_frontend* fe)
 }
 
 static struct dvb_frontend_ops tda10045_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "Philips TDA10045H DVB-T",
-               .type = FE_OFDM,
                .frequency_min = 51000000,
                .frequency_max = 858000000,
                .frequency_stepsize = 166667,
@@ -1301,9 +1302,9 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
 }
 
 static struct dvb_frontend_ops tda10046_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name = "Philips TDA10046H DVB-T",
-               .type = FE_OFDM,
                .frequency_min = 51000000,
                .frequency_max = 858000000,
                .frequency_stepsize = 166667,
index 0c37434d19e20adb34024b3421ce55cf94df34f9..a99205026751c6b77c581e31cbcbe58a70e1e60f 100644 (file)
@@ -636,8 +636,7 @@ error:
        return ret;
 }
 
-static int tda10071_set_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int tda10071_set_frontend(struct dvb_frontend *fe)
 {
        struct tda10071_priv *priv = fe->demodulator_priv;
        struct tda10071_cmd cmd;
@@ -777,8 +776,7 @@ error:
        return ret;
 }
 
-static int tda10071_get_frontend(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *p)
+static int tda10071_get_frontend(struct dvb_frontend *fe)
 {
        struct tda10071_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1217,9 +1215,9 @@ error:
 EXPORT_SYMBOL(tda10071_attach);
 
 static struct dvb_frontend_ops tda10071_ops = {
+       .delsys = { SYS_DVBT, SYS_DVBT2 },
        .info = {
                .name = "NXP TDA10071",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_tolerance = 5000,
index f2c8faac6f36426e0c7beb3f361e223b3b12cfcd..fcfe2e080cb042a0ea68e8f1ffb8bbe740ce134c 100644 (file)
@@ -267,7 +267,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
 }
 
 static int tda10086_set_inversion(struct tda10086_state *state,
-                                 struct dvb_frontend_parameters *fe_params)
+                                 struct dtv_frontend_properties *fe_params)
 {
        u8 invval = 0x80;
 
@@ -292,7 +292,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
 }
 
 static int tda10086_set_symbol_rate(struct tda10086_state *state,
-                                   struct dvb_frontend_parameters *fe_params)
+                                   struct dtv_frontend_properties *fe_params)
 {
        u8 dfn = 0;
        u8 afs = 0;
@@ -303,7 +303,7 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
        u32 tmp;
        u32 bdr;
        u32 bdri;
-       u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
+       u32 symbol_rate = fe_params->symbol_rate;
 
        dprintk ("%s %i\n", __func__, symbol_rate);
 
@@ -367,13 +367,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
 }
 
 static int tda10086_set_fec(struct tda10086_state *state,
-                           struct dvb_frontend_parameters *fe_params)
+                           struct dtv_frontend_properties *fe_params)
 {
        u8 fecval;
 
-       dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
+       dprintk("%s %i\n", __func__, fe_params->fec_inner);
 
-       switch(fe_params->u.qpsk.fec_inner) {
+       switch (fe_params->fec_inner) {
        case FEC_1_2:
                fecval = 0x00;
                break;
@@ -409,9 +409,9 @@ static int tda10086_set_fec(struct tda10086_state *state,
        return 0;
 }
 
-static int tda10086_set_frontend(struct dvb_frontend* fe,
-                                struct dvb_frontend_parameters *fe_params)
+static int tda10086_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
        struct tda10086_state *state = fe->demodulator_priv;
        int ret;
        u32 freq = 0;
@@ -425,7 +425,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
 
        /* set params */
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, fe_params);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
 
@@ -452,13 +452,14 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
        tda10086_write_mask(state, 0x10, 0x40, 0x40);
        tda10086_write_mask(state, 0x00, 0x01, 0x00);
 
-       state->symbol_rate = fe_params->u.qpsk.symbol_rate;
+       state->symbol_rate = fe_params->symbol_rate;
        state->frequency = fe_params->frequency;
        return 0;
 }
 
-static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+static int tda10086_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
        struct tda10086_state* state = fe->demodulator_priv;
        u8 val;
        int tmp;
@@ -467,7 +468,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        dprintk ("%s\n", __func__);
 
        /* check for invalid symbol rate */
-       if (fe_params->u.qpsk.symbol_rate < 500000)
+       if (fe_params->symbol_rate < 500000)
                return -EINVAL;
 
        /* calculate the updated frequency (note: we convert from Hz->kHz) */
@@ -516,34 +517,34 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
                tmp |= 0xffffff00;
        tmp = (tmp * 480 * (1<<1)) / 128;
        tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
-       fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
+       fe_params->symbol_rate = state->symbol_rate + tmp;
 
        /* the FEC */
        val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
        switch(val) {
        case 0x00:
-               fe_params->u.qpsk.fec_inner = FEC_1_2;
+               fe_params->fec_inner = FEC_1_2;
                break;
        case 0x01:
-               fe_params->u.qpsk.fec_inner = FEC_2_3;
+               fe_params->fec_inner = FEC_2_3;
                break;
        case 0x02:
-               fe_params->u.qpsk.fec_inner = FEC_3_4;
+               fe_params->fec_inner = FEC_3_4;
                break;
        case 0x03:
-               fe_params->u.qpsk.fec_inner = FEC_4_5;
+               fe_params->fec_inner = FEC_4_5;
                break;
        case 0x04:
-               fe_params->u.qpsk.fec_inner = FEC_5_6;
+               fe_params->fec_inner = FEC_5_6;
                break;
        case 0x05:
-               fe_params->u.qpsk.fec_inner = FEC_6_7;
+               fe_params->fec_inner = FEC_6_7;
                break;
        case 0x06:
-               fe_params->u.qpsk.fec_inner = FEC_7_8;
+               fe_params->fec_inner = FEC_7_8;
                break;
        case 0x07:
-               fe_params->u.qpsk.fec_inner = FEC_8_9;
+               fe_params->fec_inner = FEC_8_9;
                break;
        }
 
@@ -664,29 +665,31 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 
 static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
-       if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+       if (p->symbol_rate > 20000000) {
                fesettings->min_delay_ms = 50;
                fesettings->step_size = 2000;
                fesettings->max_drift = 8000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+       } else if (p->symbol_rate > 12000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 1500;
                fesettings->max_drift = 9000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+       } else if (p->symbol_rate > 8000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 1000;
                fesettings->max_drift = 8000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+       } else if (p->symbol_rate > 4000000) {
                fesettings->min_delay_ms = 100;
                fesettings->step_size = 500;
                fesettings->max_drift = 7000;
-       } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+       } else if (p->symbol_rate > 2000000) {
                fesettings->min_delay_ms = 200;
-               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->step_size = p->symbol_rate / 8000;
                fesettings->max_drift = 14 * fesettings->step_size;
        } else {
                fesettings->min_delay_ms = 200;
-               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->step_size =  p->symbol_rate / 8000;
                fesettings->max_drift = 18 * fesettings->step_size;
        }
 
@@ -701,10 +704,9 @@ static void tda10086_release(struct dvb_frontend* fe)
 }
 
 static struct dvb_frontend_ops tda10086_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name     = "Philips TDA10086 DVB-S",
-               .type     = FE_QPSK,
                .frequency_min    = 950000,
                .frequency_max    = 2150000,
                .frequency_stepsize = 125,     /* kHz for QPSK frontends */
index 1b1bf200c55c4b1c65dea314d5abcffcf89e7027..86da3d816498e320772a3a094702d9699b894e19 100644 (file)
@@ -1123,55 +1123,51 @@ static int release(struct dvb_frontend *fe)
        return 0;
 }
 
-/*
- * As defined on EN 300 429 Annex A and on ITU-T J.83 annex A, the DVB-C
- * roll-off factor is 0.15.
- * According with the specs, the amount of the needed bandwith is given by:
- *     Bw = Symbol_rate * (1 + 0.15)
- * As such, the maximum symbol rate supported by 6 MHz is
- *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
- *NOTE: For ITU-T J.83 Annex C, the roll-off factor is 0.13. So:
- *     max_symbol_rate = 6 MHz / 1.13 = 5309735 Baud
- *     That means that an adjustment is needed for Japan,
- *     but, as currently DRX-K is hardcoded to Annex A, let's stick
- *     with 0.15 roll-off factor.
- */
-#define MAX_SYMBOL_RATE_6MHz   5217391
 
-static int set_params(struct dvb_frontend *fe,
-                     struct dvb_frontend_parameters *params)
+static int set_params(struct dvb_frontend *fe)
 {
        struct tda_state *state = fe->tuner_priv;
        int status = 0;
        int Standard;
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       u32 delsys  = fe->dtv_property_cache.delivery_system;
 
-       state->m_Frequency = params->frequency;
+       state->m_Frequency = fe->dtv_property_cache.frequency;
 
-       if (fe->ops.info.type == FE_OFDM)
-               switch (params->u.ofdm.bandwidth) {
-               case BANDWIDTH_6_MHZ:
+       switch (delsys) {
+       case  SYS_DVBT:
+       case  SYS_DVBT2:
+               switch (bw) {
+               case 6000000:
                        Standard = HF_DVBT_6MHZ;
                        break;
-               case BANDWIDTH_7_MHZ:
+               case 7000000:
                        Standard = HF_DVBT_7MHZ;
                        break;
-               default:
-               case BANDWIDTH_8_MHZ:
+               case 8000000:
                        Standard = HF_DVBT_8MHZ;
                        break;
+               default:
+                       return -EINVAL;
                }
-       else if (fe->ops.info.type == FE_QAM) {
-               if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz)
+       case SYS_DVBC_ANNEX_A:
+       case SYS_DVBC_ANNEX_C:
+               if (bw <= 6000000)
                        Standard = HF_DVBC_6MHZ;
+               else if (bw <= 7000000)
+                       Standard = HF_DVBC_7MHZ;
                else
                        Standard = HF_DVBC_8MHZ;
-       } else
+               break;
+       default:
                return -EINVAL;
+       }
        do {
-               status = RFTrackingFiltersCorrection(state, params->frequency);
+               status = RFTrackingFiltersCorrection(state, state->m_Frequency);
                if (status < 0)
                        break;
-               status = ChannelConfiguration(state, params->frequency, Standard);
+               status = ChannelConfiguration(state, state->m_Frequency,
+                                             Standard);
                if (status < 0)
                        break;
 
index 9369f7442f273b810c8568873047153d7a1149ba..15912c96926adde19a7fbb7c50663efb146ccdf3 100644 (file)
@@ -315,18 +315,19 @@ static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda8083_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda8083_state* state = fe->demodulator_priv;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        tda8083_set_inversion (state, p->inversion);
-       tda8083_set_fec (state, p->u.qpsk.fec_inner);
-       tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate);
+       tda8083_set_fec(state, p->fec_inner);
+       tda8083_set_symbolrate(state, p->symbol_rate);
 
        tda8083_writereg (state, 0x00, 0x3c);
        tda8083_writereg (state, 0x00, 0x04);
@@ -334,16 +335,17 @@ static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        return 0;
 }
 
-static int tda8083_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda8083_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda8083_state* state = fe->demodulator_priv;
 
        /*  FIXME: get symbolrate & frequency offset...*/
        /*p->frequency = ???;*/
        p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
                        INVERSION_ON : INVERSION_OFF;
-       p->u.qpsk.fec_inner = tda8083_get_fec (state);
-       /*p->u.qpsk.symbol_rate = tda8083_get_symbolrate (state);*/
+       p->fec_inner = tda8083_get_fec(state);
+       /*p->symbol_rate = tda8083_get_symbolrate (state);*/
 
        return 0;
 }
@@ -438,10 +440,9 @@ error:
 }
 
 static struct dvb_frontend_ops tda8083_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "Philips TDA8083 DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 920000,     /* TDA8060 */
                .frequency_max          = 2200000,    /* TDA8060 */
                .frequency_stepsize     = 125,   /* kHz for QPSK frontends */
index 06c94800b9402955ccbf799f8ee66e93c2a4f956..04bbcc24de0a7834c0b6b4d1132157472cd173a5 100644 (file)
@@ -71,8 +71,9 @@ static int tda826x_sleep(struct dvb_frontend *fe)
        return (ret == 1) ? 0 : ret;
 }
 
-static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda826x_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct tda826x_priv *priv = fe->tuner_priv;
        int ret;
        u32 div;
@@ -83,11 +84,11 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
 
        dprintk("%s:\n", __func__);
 
-       div = (params->frequency + (1000-1)) / 1000;
+       div = (p->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;
+       ksyms = p->symbol_rate / 1000;
        bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
        if (bandwidth < 5)
                bandwidth = 5;
index 51f1706786507ad20521a7e109e77a44068d2527..17750985db0cacfc15af5ccec345a8b4ee91dede 100644 (file)
@@ -40,24 +40,25 @@ static struct tda1004x_config alps_tdhd1_204a_config = {
        .request_firmware = alps_tdhd1_204_request_firmware
 };
 
-static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct i2c_adapter *i2c = fe->tuner_priv;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
        u32 div;
 
-       div = (params->frequency + 36166666) / 166666;
+       div = (p->frequency + 36166666) / 166666;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x85;
 
-       if (params->frequency >= 174000000 && params->frequency <= 230000000)
+       if (p->frequency >= 174000000 && p->frequency <= 230000000)
                data[3] = 0x02;
-       else if (params->frequency >= 470000000 && params->frequency <= 823000000)
+       else if (p->frequency >= 470000000 && p->frequency <= 823000000)
                data[3] = 0x0C;
-       else if (params->frequency > 823000000 && params->frequency <= 862000000)
+       else if (p->frequency > 823000000 && p->frequency <= 862000000)
                data[3] = 0x8C;
        else
                return -EINVAL;
index bcb95c2ef296092dfb50fcc18196cd5204fe97eb..029384d1fdddd0caa08a333b37fb50968df0caa5 100644 (file)
@@ -67,9 +67,9 @@ static int tua6100_sleep(struct dvb_frontend *fe)
        return (ret == 1) ? 0 : ret;
 }
 
-static int tua6100_set_params(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *params)
+static int tua6100_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct tua6100_priv *priv = fe->tuner_priv;
        u32 div;
        u32 prediv;
@@ -85,36 +85,37 @@ static int tua6100_set_params(struct dvb_frontend *fe,
 #define _ri 4000000
 
        // setup register 0
-       if (params->frequency < 2000000) {
+       if (c->frequency < 2000000)
                reg0[1] = 0x03;
-       } else {
+       else
                reg0[1] = 0x07;
-       }
 
        // setup register 1
-       if (params->frequency < 1630000) {
+       if (c->frequency < 1630000)
                reg1[1] = 0x2c;
-       } else {
+       else
                reg1[1] = 0x0c;
-       }
+
        if (_P == 64)
                reg1[1] |= 0x40;
-       if (params->frequency >= 1525000)
+       if (c->frequency >= 1525000)
                reg1[1] |= 0x80;
 
        // register 2
        reg2[1] = (_R >> 8) & 0x03;
        reg2[2] = _R;
-       if (params->frequency < 1455000) {
+       if (c->frequency < 1455000)
                reg2[1] |= 0x1c;
-       } else if (params->frequency < 1630000) {
+       else if (c->frequency < 1630000)
                reg2[1] |= 0x0c;
-       } else {
+       else
                reg2[1] |= 0x1c;
-       }
 
-       // The N divisor ratio (note: params->frequency is in kHz, but we need it in Hz)
-       prediv = (params->frequency * _R) / (_ri / 1000);
+       /*
+        * The N divisor ratio (note: c->frequency is in kHz, but we
+        * need it in Hz)
+        */
+       prediv = (c->frequency * _R) / (_ri / 1000);
        div = prediv / _P;
        reg1[1] |= (div >> 9) & 0x03;
        reg1[2] = div >> 1;
index 550a07a8a9975d253b9e39482d5e4cc0b040adb8..bb42b563c42d7761353747f74d682c6ac0999f6b 100644 (file)
@@ -205,25 +205,26 @@ static int ves1820_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1820_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ves1820_state* state = fe->demodulator_priv;
        static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
        static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
        static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
        static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
        static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
-       int real_qam = p->u.qam.modulation - QAM_16;
+       int real_qam = p->modulation - QAM_16;
 
        if (real_qam < 0 || real_qam > 4)
                return -EINVAL;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
+       ves1820_set_symbolrate(state, p->symbol_rate);
        ves1820_writereg(state, 0x34, state->pwm);
 
        ves1820_writereg(state, 0x01, reg0x01[real_qam]);
@@ -309,8 +310,9 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1820_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ves1820_state* state = fe->demodulator_priv;
        int sync;
        s8 afc = 0;
@@ -320,7 +322,7 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        if (verbose) {
                /* AFC only valid when carrier has been recovered */
                printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
-                       "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10);
+                       "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->symbol_rate * afc) >> 10);
        }
 
        if (!state->config->invert) {
@@ -329,13 +331,13 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
                p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
        }
 
-       p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+       p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
 
-       p->u.qam.fec_inner = FEC_NONE;
+       p->fec_inner = FEC_NONE;
 
        p->frequency = ((p->frequency + 31250) / 62500) * 62500;
        if (sync & 2)
-               p->frequency -= ((s32) p->u.qam.symbol_rate * afc) >> 10;
+               p->frequency -= ((s32) p->symbol_rate * afc) >> 10;
 
        return 0;
 }
@@ -405,10 +407,9 @@ error:
 }
 
 static struct dvb_frontend_ops ves1820_ops = {
-
+       .delsys = { SYS_DVBC_ANNEX_A },
        .info = {
                .name = "VLSI VES1820 DVB-C",
-               .type = FE_QAM,
                .frequency_stepsize = 62500,
                .frequency_min = 47000000,
                .frequency_max = 862000000,
index 8d7854c2fb0c142683a2c823a3447af61c637438..9c17eacaec24f738e63028e61cb9d7d3d793c9ba 100644 (file)
@@ -46,6 +46,7 @@ struct ves1x93_state {
        u8 *init_1x93_wtab;
        u8 tab_size;
        u8 demod_type;
+       u32 frequency;
 };
 
 static int debug;
@@ -384,31 +385,34 @@ static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
-static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1x93_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ves1x93_state* state = fe->demodulator_priv;
 
        if (fe->ops.tuner_ops.set_params) {
-               fe->ops.tuner_ops.set_params(fe, p);
+               fe->ops.tuner_ops.set_params(fe);
                if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
        ves1x93_set_inversion (state, p->inversion);
-       ves1x93_set_fec (state, p->u.qpsk.fec_inner);
-       ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
+       ves1x93_set_fec(state, p->fec_inner);
+       ves1x93_set_symbolrate(state, p->symbol_rate);
        state->inversion = p->inversion;
+       state->frequency = p->frequency;
 
        return 0;
 }
 
-static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1x93_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ves1x93_state* state = fe->demodulator_priv;
        int afc;
 
        afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
-       afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
+       afc = (afc * (int)(p->symbol_rate/1000/8))/16;
 
-       p->frequency -= afc;
+       p->frequency = state->frequency - afc;
 
        /*
         * inversion indicator is only valid
@@ -417,7 +421,7 @@ static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        if (state->inversion == INVERSION_AUTO)
                p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ?
                                INVERSION_OFF : INVERSION_ON;
-       p->u.qpsk.fec_inner = ves1x93_get_fec (state);
+       p->fec_inner = ves1x93_get_fec(state);
        /*  XXX FIXME: timing offset !! */
 
        return 0;
@@ -506,10 +510,9 @@ error:
 }
 
 static struct dvb_frontend_ops ves1x93_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "VLSI VES1x93 DVB-S",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 125,           /* kHz for QPSK frontends */
index 81aa984c551f3516b7179aaab4624d4039252df9..0903d461b8fa769ca5fe2db4a918edfc2388d4bf 100644 (file)
@@ -305,12 +305,12 @@ static int zl10036_set_gain_params(struct zl10036_state *state,
        return zl10036_write(state, buf, sizeof(buf));
 }
 
-static int zl10036_set_params(struct dvb_frontend *fe,
-               struct dvb_frontend_parameters *params)
+static int zl10036_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct zl10036_state *state = fe->tuner_priv;
        int ret = 0;
-       u32 frequency = params->frequency;
+       u32 frequency = p->frequency;
        u32 fbw;
        int i;
        u8 c;
@@ -326,7 +326,7 @@ static int zl10036_set_params(struct dvb_frontend *fe,
         * fBW = (alpha*symbolrate)/(2*0.8)
         * 1.35 / (2*0.8) = 27 / 32
         */
-       fbw = (27 * params->u.qpsk.symbol_rate) / 32;
+       fbw = (27 * p->symbol_rate) / 32;
 
        /* scale to kHz */
        fbw /= 1000;
@@ -353,7 +353,7 @@ static int zl10036_set_params(struct dvb_frontend *fe,
        if (ret < 0)
                goto error;
 
-       ret = zl10036_set_frequency(state, params->frequency);
+       ret = zl10036_set_frequency(state, p->frequency);
        if (ret < 0)
                goto error;
 
index c085e58a94bfe7d64b876a3421d244eb392b473d..eff9c5fde50ad65662948cb9109341a0c25a7e0f 100644 (file)
@@ -176,9 +176,9 @@ static int zl10039_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int zl10039_set_params(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *params)
+static int zl10039_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct zl10039_state *state = fe->tuner_priv;
        u8 buf[6];
        u8 bf;
@@ -188,12 +188,12 @@ static int zl10039_set_params(struct dvb_frontend *fe,
 
        dprintk("%s\n", __func__);
        dprintk("Set frequency = %d, symbol rate = %d\n",
-                       params->frequency, params->u.qpsk.symbol_rate);
+                       c->frequency, c->symbol_rate);
 
        /* Assumed 10.111 MHz crystal oscillator */
        /* Cancelled num/den 80 to prevent overflow */
-       div = (params->frequency * 1000) / 126387;
-       fbw = (params->u.qpsk.symbol_rate * 27) / 32000;
+       div = (c->frequency * 1000) / 126387;
+       fbw = (c->symbol_rate * 27) / 32000;
        /* Cancelled num/den 10 to prevent overflow */
        bf = ((fbw * 5088) / 1011100) - 1;
 
index adbbf6d3d044cc4d491032638b7498a2ee422f3e..ac7237891374f68456d3c687c4924b11f04b654b 100644 (file)
@@ -37,9 +37,9 @@ struct zl10353_state {
 
        struct zl10353_config config;
 
-       enum fe_bandwidth bandwidth;
-       u32 ucblocks;
-       u32 frequency;
+       u32 bandwidth;
+       u32 ucblocks;
+       u32 frequency;
 };
 
 static int debug;
@@ -122,30 +122,17 @@ static void zl10353_dump_regs(struct dvb_frontend *fe)
 }
 
 static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
-                                     enum fe_bandwidth bandwidth,
+                                     u32 bandwidth,
                                      u16 *nominal_rate)
 {
        struct zl10353_state *state = fe->demodulator_priv;
        u32 adc_clock = 450560; /* 45.056 MHz */
        u64 value;
-       u8 bw;
+       u8 bw = bandwidth / 1000000;
 
        if (state->config.adc_clock)
                adc_clock = state->config.adc_clock;
 
-       switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
-               bw = 6;
-               break;
-       case BANDWIDTH_7_MHZ:
-               bw = 7;
-               break;
-       case BANDWIDTH_8_MHZ:
-       default:
-               bw = 8;
-               break;
-       }
-
        value = (u64)10 * (1 << 23) / 7 * 125;
        value = (bw * value) + adc_clock / 2;
        do_div(value, adc_clock);
@@ -192,16 +179,15 @@ static int zl10353_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static int zl10353_set_parameters(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *param)
+static int zl10353_set_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct zl10353_state *state = fe->demodulator_priv;
        u16 nominal_rate, input_freq;
        u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
        u16 tps = 0;
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
 
-       state->frequency = param->frequency;
+       state->frequency = c->frequency;
 
        zl10353_single_write(fe, RESET, 0x80);
        udelay(200);
@@ -211,42 +197,44 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
 
        zl10353_single_write(fe, AGC_TARGET, 0x28);
 
-       if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
+       if (c->transmission_mode != TRANSMISSION_MODE_AUTO)
                acq_ctl |= (1 << 0);
-       if (op->guard_interval != GUARD_INTERVAL_AUTO)
+       if (c->guard_interval != GUARD_INTERVAL_AUTO)
                acq_ctl |= (1 << 1);
        zl10353_single_write(fe, ACQ_CTL, acq_ctl);
 
-       switch (op->bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                /* These are extrapolated from the 7 and 8MHz values */
                zl10353_single_write(fe, MCLK_RATIO, 0x97);
                zl10353_single_write(fe, 0x64, 0x34);
                zl10353_single_write(fe, 0xcc, 0xdd);
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                zl10353_single_write(fe, MCLK_RATIO, 0x86);
                zl10353_single_write(fe, 0x64, 0x35);
                zl10353_single_write(fe, 0xcc, 0x73);
                break;
-       case BANDWIDTH_8_MHZ:
        default:
+               c->bandwidth_hz = 8000000;
+               /* fall though */
+       case 8000000:
                zl10353_single_write(fe, MCLK_RATIO, 0x75);
                zl10353_single_write(fe, 0x64, 0x36);
                zl10353_single_write(fe, 0xcc, 0x73);
        }
 
-       zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
+       zl10353_calc_nominal_rate(fe, c->bandwidth_hz, &nominal_rate);
        zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
        zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
-       state->bandwidth = op->bandwidth;
+       state->bandwidth = c->bandwidth_hz;
 
        zl10353_calc_input_freq(fe, &input_freq);
        zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
        zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
 
        /* Hint at TPS settings */
-       switch (op->code_rate_HP) {
+       switch (c->code_rate_HP) {
        case FEC_2_3:
                tps |= (1 << 7);
                break;
@@ -266,7 +254,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       switch (op->code_rate_LP) {
+       switch (c->code_rate_LP) {
        case FEC_2_3:
                tps |= (1 << 4);
                break;
@@ -283,14 +271,14 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        case FEC_AUTO:
                break;
        case FEC_NONE:
-               if (op->hierarchy_information == HIERARCHY_AUTO ||
-                   op->hierarchy_information == HIERARCHY_NONE)
+               if (c->hierarchy == HIERARCHY_AUTO ||
+                   c->hierarchy == HIERARCHY_NONE)
                        break;
        default:
                return -EINVAL;
        }
 
-       switch (op->constellation) {
+       switch (c->modulation) {
        case QPSK:
                break;
        case QAM_AUTO:
@@ -304,7 +292,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       switch (op->transmission_mode) {
+       switch (c->transmission_mode) {
        case TRANSMISSION_MODE_2K:
        case TRANSMISSION_MODE_AUTO:
                break;
@@ -315,7 +303,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       switch (op->guard_interval) {
+       switch (c->guard_interval) {
        case GUARD_INTERVAL_1_32:
        case GUARD_INTERVAL_AUTO:
                break;
@@ -332,7 +320,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                return -EINVAL;
        }
 
-       switch (op->hierarchy_information) {
+       switch (c->hierarchy) {
        case HIERARCHY_AUTO:
        case HIERARCHY_NONE:
                break;
@@ -362,12 +350,12 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
         */
        if (state->config.no_tuner) {
                if (fe->ops.tuner_ops.set_params) {
-                       fe->ops.tuner_ops.set_params(fe, param);
+                       fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl)
                                fe->ops.i2c_gate_ctrl(fe, 0);
                }
        } else if (fe->ops.tuner_ops.calc_regs) {
-               fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5);
+               fe->ops.tuner_ops.calc_regs(fe, pllbuf + 1, 5);
                pllbuf[1] <<= 1;
                zl10353_write(fe, pllbuf, sizeof(pllbuf));
        }
@@ -383,11 +371,10 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        return 0;
 }
 
-static int zl10353_get_parameters(struct dvb_frontend *fe,
-                                 struct dvb_frontend_parameters *param)
+static int zl10353_get_parameters(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct zl10353_state *state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *op = &param->u.ofdm;
        int s6, s9;
        u16 tps;
        static const u8 tps_fec_to_api[8] = {
@@ -411,66 +398,66 @@ static int zl10353_get_parameters(struct dvb_frontend *fe,
        tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
              zl10353_read_register(state, TPS_RECEIVED_0);
 
-       op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
-       op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
+       c->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
+       c->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
 
        switch ((tps >> 13) & 3) {
        case 0:
-               op->constellation = QPSK;
+               c->modulation = QPSK;
                break;
        case 1:
-               op->constellation = QAM_16;
+               c->modulation = QAM_16;
                break;
        case 2:
-               op->constellation = QAM_64;
+               c->modulation = QAM_64;
                break;
        default:
-               op->constellation = QAM_AUTO;
+               c->modulation = QAM_AUTO;
                break;
        }
 
-       op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
+       c->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
                                               TRANSMISSION_MODE_2K;
 
        switch ((tps >> 2) & 3) {
        case 0:
-               op->guard_interval = GUARD_INTERVAL_1_32;
+               c->guard_interval = GUARD_INTERVAL_1_32;
                break;
        case 1:
-               op->guard_interval = GUARD_INTERVAL_1_16;
+               c->guard_interval = GUARD_INTERVAL_1_16;
                break;
        case 2:
-               op->guard_interval = GUARD_INTERVAL_1_8;
+               c->guard_interval = GUARD_INTERVAL_1_8;
                break;
        case 3:
-               op->guard_interval = GUARD_INTERVAL_1_4;
+               c->guard_interval = GUARD_INTERVAL_1_4;
                break;
        default:
-               op->guard_interval = GUARD_INTERVAL_AUTO;
+               c->guard_interval = GUARD_INTERVAL_AUTO;
                break;
        }
 
        switch ((tps >> 10) & 7) {
        case 0:
-               op->hierarchy_information = HIERARCHY_NONE;
+               c->hierarchy = HIERARCHY_NONE;
                break;
        case 1:
-               op->hierarchy_information = HIERARCHY_1;
+               c->hierarchy = HIERARCHY_1;
                break;
        case 2:
-               op->hierarchy_information = HIERARCHY_2;
+               c->hierarchy = HIERARCHY_2;
                break;
        case 3:
-               op->hierarchy_information = HIERARCHY_4;
+               c->hierarchy = HIERARCHY_4;
                break;
        default:
-               op->hierarchy_information = HIERARCHY_AUTO;
+               c->hierarchy = HIERARCHY_AUTO;
                break;
        }
 
-       param->frequency = state->frequency;
-       op->bandwidth = state->bandwidth;
-       param->inversion = INVERSION_AUTO;
+       c->frequency = state->frequency;
+       c->bandwidth_hz = state->bandwidth;
+       c->inversion = INVERSION_AUTO;
 
        return 0;
 }
@@ -651,10 +638,9 @@ error:
 }
 
 static struct dvb_frontend_ops zl10353_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Zarlink ZL10353 DVB-T",
-               .type                   = FE_OFDM,
                .frequency_min          = 174000000,
                .frequency_max          = 862000000,
                .frequency_stepsize     = 166667,
index 2ae0afa7756be4b27442874a3526ef2d12ddac69..ad013e93ed11d7bd05638ebf7eb5a398c4631244 100644 (file)
@@ -83,9 +83,9 @@ u8 lgtdqcs001f_inittab[] = {
 #define MANTIS_MODEL_NAME      "VP-1033"
 #define MANTIS_DEV_TYPE                "DVB-S/DSS"
 
-int lgtdqcs001f_tuner_set(struct dvb_frontend *fe,
-                         struct dvb_frontend_parameters *params)
+int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mantis_pci *mantis       = fe->dvb->priv;
        struct i2c_adapter *adapter     = &mantis->adapter;
 
@@ -95,14 +95,14 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe,
 
        struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
 
-       div = params->frequency / 250;
+       div = p->frequency / 250;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] =  div & 0xff;
        buf[2] =  0x83;
        buf[3] =  0xc0;
 
-       if (params->frequency < 1531000)
+       if (p->frequency < 1531000)
                buf[3] |= 0x04;
        else
                buf[3] &= ~0x04;
index 06da0ddf05a77b46bcb582a274019499a6cb5f67..1ca6837fbe468a8da8f82fe7818a4240880e5004 100644 (file)
@@ -65,8 +65,9 @@ static u8 read_pwm(struct mantis_pci *mantis)
        return pwm;
 }
 
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mantis_pci *mantis = fe->dvb->priv;
        struct i2c_adapter *adapter = &mantis->adapter;
 
@@ -77,13 +78,13 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten
 #define CU1216_IF 36125000
 #define TUNER_MUL 62500
 
-       u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+       u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0xce;
-       buf[3] = (params->frequency < 150000000 ? 0x01 :
-                 params->frequency < 445000000 ? 0x02 : 0x04);
+       buf[3] = (p->frequency < 150000000 ? 0x01 :
+                 p->frequency < 445000000 ? 0x02 : 0x04);
        buf[4] = 0xde;
        buf[5] = 0x20;
 
index f72b137b7652b94eded9ddb3351b410c1993de0b..d480741afd786dc3e13420077d43f4567f38e666 100644 (file)
@@ -47,8 +47,9 @@ struct tda10023_config vp2040_tda10023_cu1216_config = {
        .invert         = 1,
 };
 
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct mantis_pci *mantis       = fe->dvb->priv;
        struct i2c_adapter *adapter     = &mantis->adapter;
 
@@ -59,13 +60,13 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten
 #define CU1216_IF 36125000
 #define TUNER_MUL 62500
 
-       u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+       u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0xce;
-       buf[3] = (params->frequency < 150000000 ? 0x01 :
-                 params->frequency < 445000000 ? 0x02 : 0x04);
+       buf[3] = (p->frequency < 150000000 ? 0x01 :
+                 p->frequency < 445000000 ? 0x02 : 0x04);
        buf[4] = 0xde;
        buf[5] = 0x20;
 
index 056419228363f8344eefbab82ef8b05eb24feace..8418c02bcefeb8ec7015d42eb4517f9a8a4cbff6 100644 (file)
@@ -218,7 +218,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
        memset(&config, 0, sizeof(config));
        config.adr = 0x29 + (chan->number ^ 2);
 
-       chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2);
+       chan->fe = dvb_attach(drxk_attach, &config, i2c);
        if (!chan->fe) {
                printk(KERN_ERR "No DRXK found!\n");
                return -ENODEV;
index 80fb5100446156e99840f52cbe37a62940063a39..e1f20c236989584161afa2623a52f39b75c68062 100644 (file)
@@ -445,9 +445,9 @@ static inline u32 divide(u32 numerator, u32 denominator)
 }
 
 /* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
-                                        struct dvb_frontend_parameters *p)
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct pluto *pluto = frontend_to_pluto(fe);
        struct i2c_msg msg;
        int ret;
@@ -478,7 +478,7 @@ static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
        else
                buf[3] = 0x04;
 
-       if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+       if (p->bandwidth_hz == 8000000)
                buf[3] |= 0x08;
 
        if (sizeof(buf) == 6) {
index 451641c0c1d2d41ec6bf0ad54183c8511157ddb9..d980dfb21e5e1a2e78887ff51a9e2123c313a3dd 100644 (file)
@@ -385,7 +385,7 @@ va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
 
 static int
 va1j5jf8007s_tune(struct dvb_frontend *fe,
-                 struct dvb_frontend_parameters *params,
+                 bool re_tune,
                  unsigned int mode_flags,  unsigned int *delay,
                  fe_status_t *status)
 {
@@ -395,7 +395,7 @@ va1j5jf8007s_tune(struct dvb_frontend *fe,
 
        state = fe->demodulator_priv;
 
-       if (params != NULL)
+       if (re_tune)
                state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
 
        switch (state->tune_state) {
@@ -579,9 +579,9 @@ static void va1j5jf8007s_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops va1j5jf8007s_ops = {
+       .delsys = { SYS_ISDBS },
        .info = {
                .name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
-               .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
                .frequency_stepsize = 1000,
index 0f085c3e571b71904fbdc37401bd4d3c63bb724e..2db15159d514daf498791e668a4eab8cd1a91c7d 100644 (file)
@@ -264,7 +264,7 @@ static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
 
 static int
 va1j5jf8007t_tune(struct dvb_frontend *fe,
-                 struct dvb_frontend_parameters *params,
+                 bool re_tune,
                  unsigned int mode_flags,  unsigned int *delay,
                  fe_status_t *status)
 {
@@ -274,7 +274,7 @@ va1j5jf8007t_tune(struct dvb_frontend *fe,
 
        state = fe->demodulator_priv;
 
-       if (params != NULL)
+       if (re_tune)
                state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
 
        switch (state->tune_state) {
@@ -428,9 +428,9 @@ static void va1j5jf8007t_release(struct dvb_frontend *fe)
 }
 
 static struct dvb_frontend_ops va1j5jf8007t_ops = {
+       .delsys = { SYS_ISDBT },
        .info = {
                .name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
-               .type = FE_OFDM,
                .frequency_min = 90000000,
                .frequency_max = 770000000,
                .frequency_stepsize = 142857,
index 37c594f827825af53364797fea1c8b219588af30..654685c9303e58e8eff7edd15c50aae0c6daeaec 100644 (file)
@@ -50,7 +50,7 @@ struct smsdvb_client_t {
        struct completion       tune_done;
 
        /* todo: save freq/band instead whole struct */
-       struct dvb_frontend_parameters fe_params;
+       struct dtv_frontend_properties fe_params;
 
        struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
        int event_fe_state;
@@ -591,8 +591,7 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
        return 0;
 }
 
-static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
-                                   struct dvb_frontend_parameters *p)
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct smsdvb_client_t *client =
@@ -658,8 +657,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
                                           &client->tune_done);
 }
 
-static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
-                                    struct dvb_frontend_parameters *p)
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct smsdvb_client_t *client =
@@ -723,8 +721,7 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
                                           &client->tune_done);
 }
 
-static int smsdvb_set_frontend(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *fep)
+static int smsdvb_set_frontend(struct dvb_frontend *fe)
 {
        struct smsdvb_client_t *client =
                container_of(fe, struct smsdvb_client_t, frontend);
@@ -733,18 +730,18 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
        switch (smscore_get_device_mode(coredev)) {
        case DEVICE_MODE_DVBT:
        case DEVICE_MODE_DVBT_BDA:
-               return smsdvb_dvbt_set_frontend(fe, fep);
+               return smsdvb_dvbt_set_frontend(fe);
        case DEVICE_MODE_ISDBT:
        case DEVICE_MODE_ISDBT_BDA:
-               return smsdvb_isdbt_set_frontend(fe, fep);
+               return smsdvb_isdbt_set_frontend(fe);
        default:
                return -EINVAL;
        }
 }
 
-static int smsdvb_get_frontend(struct dvb_frontend *fe,
-                              struct dvb_frontend_parameters *fep)
+static int smsdvb_get_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct smsdvb_client_t *client =
                container_of(fe, struct smsdvb_client_t, frontend);
 
@@ -752,7 +749,7 @@ static int smsdvb_get_frontend(struct dvb_frontend *fe,
 
        /* todo: */
        memcpy(fep, &client->fe_params,
-              sizeof(struct dvb_frontend_parameters));
+              sizeof(struct dtv_frontend_properties));
 
        return 0;
 }
@@ -789,7 +786,6 @@ static void smsdvb_release(struct dvb_frontend *fe)
 static struct dvb_frontend_ops smsdvb_fe_ops = {
        .info = {
                .name                   = "Siano Mobile Digital MDTV Receiver",
-               .type                   = FE_OFDM,
                .frequency_min          = 44250000,
                .frequency_max          = 867250000,
                .frequency_stepsize     = 250000,
@@ -873,6 +869,17 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
        memcpy(&client->frontend.ops, &smsdvb_fe_ops,
               sizeof(struct dvb_frontend_ops));
 
+       switch (smscore_get_device_mode(coredev)) {
+       case DEVICE_MODE_DVBT:
+       case DEVICE_MODE_DVBT_BDA:
+               smsdvb_fe_ops.delsys[0] = SYS_DVBT;
+               break;
+       case DEVICE_MODE_ISDBT:
+       case DEVICE_MODE_ISDBT_BDA:
+               smsdvb_fe_ops.delsys[0] = SYS_ISDBT;
+               break;
+       }
+
        rc = dvb_register_frontend(&client->adapter, &client->frontend);
        if (rc < 0) {
                sms_err("frontend registration failed %d", rc);
index 3d20719fce1a114d7c630560235ce53b1e022b4b..6ecbcf614878fa186be24be1a39f8a07365b3cc9 100644 (file)
@@ -991,7 +991,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
 
        if (feed->type == DMX_TYPE_TS) {
                if ((feed->ts_type & TS_DECODER) &&
-                   (feed->pes_type < DMX_TS_PES_OTHER)) {
+                   (feed->pes_type <= DMX_TS_PES_PCR)) {
                        switch (demux->dmx.frontend->source) {
                        case DMX_MEMORY_FE:
                                if (feed->ts_type & TS_DECODER)
@@ -1568,20 +1568,27 @@ static int get_firmware(struct av7110* av7110)
        return ret;
 }
 
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u8 pwr = 0;
        u8 buf[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       u32 div = (params->frequency + 479500) / 125;
+       u32 div = (p->frequency + 479500) / 125;
 
-       if (params->frequency > 2000000) pwr = 3;
-       else if (params->frequency > 1800000) pwr = 2;
-       else if (params->frequency > 1600000) pwr = 1;
-       else if (params->frequency > 1200000) pwr = 0;
-       else if (params->frequency >= 1100000) pwr = 1;
-       else pwr = 2;
+       if (p->frequency > 2000000)
+               pwr = 3;
+       else if (p->frequency > 1800000)
+               pwr = 2;
+       else if (p->frequency > 1600000)
+               pwr = 1;
+       else if (p->frequency > 1200000)
+               pwr = 0;
+       else if (p->frequency >= 1100000)
+               pwr = 1;
+       else
+               pwr = 2;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
@@ -1604,19 +1611,20 @@ static struct ves1x93_config alps_bsrv2_config = {
        .invert_pwm = 0,
 };
 
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (params->frequency + 35937500 + 31250) / 62500;
+       div = (p->frequency + 35937500 + 31250) / 62500;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x85 | ((div >> 10) & 0x60);
-       data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+       data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1635,14 +1643,15 @@ static struct ves1820_config alps_tdbe2_config = {
 
 
 
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = params->frequency / 125;
+       div = p->frequency / 125;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x8e;
@@ -1661,11 +1670,12 @@ static struct tda8083_config grundig_29504_451_config = {
 
 
 
-static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
-       u32 f = params->frequency;
+       u32 f = p->frequency;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
@@ -1692,16 +1702,17 @@ static struct ves1820_config philips_cd1516_config = {
 
 
 
-static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div, pwr;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (params->frequency + 36200000) / 166666;
+       div = (p->frequency + 36200000) / 166666;
 
-       if (params->frequency <= 782000000)
+       if (p->frequency <= 782000000)
                pwr = 1;
        else
                pwr = 2;
@@ -1829,8 +1840,9 @@ static u8 nexusca_stv0297_inittab[] = {
        0xff, 0xff,
 };
 
-static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
        u8 data[4];
@@ -1838,19 +1850,19 @@ static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_
        struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
        int i;
 
-       div = (params->frequency + 36150000 + 31250) / 62500;
+       div = (p->frequency + 36150000 + 31250) / 62500;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0xce;
 
-       if (params->frequency < 45000000)
+       if (p->frequency < 45000000)
                return -EINVAL;
-       else if (params->frequency < 137000000)
+       else if (p->frequency < 137000000)
                data[3] = 0x01;
-       else if (params->frequency < 403000000)
+       else if (p->frequency < 403000000)
                data[3] = 0x02;
-       else if (params->frequency < 860000000)
+       else if (p->frequency < 860000000)
                data[3] = 0x04;
        else
                return -EINVAL;
@@ -1884,27 +1896,36 @@ static struct stv0297_config nexusca_stv0297_config = {
 
 
 
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
        u8 cfg, cpump, band_select;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (36125000 + params->frequency) / 166666;
+       div = (36125000 + p->frequency) / 166666;
 
        cfg = 0x88;
 
-       if (params->frequency < 175000000) cpump = 2;
-       else if (params->frequency < 390000000) cpump = 1;
-       else if (params->frequency < 470000000) cpump = 2;
-       else if (params->frequency < 750000000) cpump = 1;
-       else cpump = 3;
+       if (p->frequency < 175000000)
+               cpump = 2;
+       else if (p->frequency < 390000000)
+               cpump = 1;
+       else if (p->frequency < 470000000)
+               cpump = 2;
+       else if (p->frequency < 750000000)
+               cpump = 1;
+       else
+               cpump = 3;
 
-       if (params->frequency < 175000000) band_select = 0x0e;
-       else if (params->frequency < 470000000) band_select = 0x05;
-       else band_select = 0x03;
+       if (p->frequency < 175000000)
+               band_select = 0x0e;
+       else if (p->frequency < 470000000)
+               band_select = 0x05;
+       else
+               band_select = 0x03;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
@@ -1964,15 +1985,14 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
        return ret;
 }
 
-static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int av7110_fe_set_frontend(struct dvb_frontend *fe)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
        int ret = av7110_fe_lock_fix(av7110, 0);
-       if (!ret) {
-               av7110->saved_fe_params = *params;
-               ret = av7110->fe_set_frontend(fe, params);
-       }
+       if (!ret)
+               ret = av7110->fe_set_frontend(fe);
+
        return ret;
 }
 
@@ -2081,7 +2101,7 @@ static void dvb_s_recover(struct av7110* av7110)
        msleep(20);
        av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
 
-       av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
+       av7110_fe_set_frontend(av7110->fe);
 }
 
 static u8 read_pwm(struct av7110* av7110)
index d85b8512ac307cb2bfa59f3d695036a1a6a35515..88b3b2d6cc0e9dbcbf04d50987e40b0576b9c6ae 100644 (file)
@@ -272,7 +272,6 @@ struct av7110 {
 
        /* crash recovery */
        void                            (*recover)(struct av7110* av7110);
-       struct dvb_frontend_parameters  saved_fe_params;
        fe_sec_voltage_t                saved_voltage;
        fe_sec_tone_mode_t              saved_tone;
        struct dvb_diseqc_master_cmd    saved_master_cmd;
@@ -286,7 +285,7 @@ struct av7110 {
        int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
        int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
        int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
-       int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+       int (*fe_set_frontend)(struct dvb_frontend *fe);
 };
 
 
index 78d32f7e49fc569b84d16f68615f998c2c4dfeb4..8b32e282bf5d50d3bae319b6fa1b411e7ff6ada4 100644 (file)
@@ -502,33 +502,33 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
        return 0;
 }
 
-static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
-                                                struct dvb_frontend_parameters *params)
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u32 div;
        u8 buf[4];
        struct budget *budget = (struct budget *) fe->dvb->priv;
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
+       if ((c->frequency < 950000) || (c->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (125 - 1)) / 125;    // round correctly
+       div = (c->frequency + (125 - 1)) / 125; /* round correctly */
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
        buf[3] = 0x20;
 
-       if (params->u.qpsk.symbol_rate < 4000000)
+       if (c->symbol_rate < 4000000)
                buf[3] |= 1;
 
-       if (params->frequency < 1250000)
+       if (c->frequency < 1250000)
                buf[3] |= 0;
-       else if (params->frequency < 1550000)
+       else if (c->frequency < 1550000)
                buf[3] |= 0x40;
-       else if (params->frequency < 2050000)
+       else if (c->frequency < 2050000)
                buf[3] |= 0x80;
-       else if (params->frequency < 2150000)
+       else if (c->frequency < 2150000)
                buf[3] |= 0xC0;
 
        if (fe->ops.i2c_gate_ctrl)
@@ -617,8 +617,9 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
 };
 
-static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget *budget = (struct budget *) fe->dvb->priv;
        u8 buf[6];
        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -627,13 +628,13 @@ static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
 #define CU1216_IF 36125000
 #define TUNER_MUL 62500
 
-       u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+       u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0xce;
-       buf[3] = (params->frequency < 150000000 ? 0x01 :
-                 params->frequency < 445000000 ? 0x02 : 0x04);
+       buf[3] = (c->frequency < 150000000 ? 0x01 :
+                 c->frequency < 445000000 ? 0x02 : 0x04);
        buf[4] = 0xde;
        buf[5] = 0x20;
 
@@ -697,8 +698,9 @@ static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget *budget = (struct budget *) fe->dvb->priv;
        u8 tuner_buf[4];
        struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
@@ -707,7 +709,7 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
        u8 band, cp, filter;
 
        // determine charge pump
-       tuner_frequency = params->frequency + 36166000;
+       tuner_frequency = c->frequency + 36166000;
        if (tuner_frequency < 87000000)
                return -EINVAL;
        else if (tuner_frequency < 130000000)
@@ -732,28 +734,28 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
                return -EINVAL;
 
        // determine band
-       if (params->frequency < 49000000)
+       if (c->frequency < 49000000)
                return -EINVAL;
-       else if (params->frequency < 161000000)
+       else if (c->frequency < 161000000)
                band = 1;
-       else if (params->frequency < 444000000)
+       else if (c->frequency < 444000000)
                band = 2;
-       else if (params->frequency < 861000000)
+       else if (c->frequency < 861000000)
                band = 4;
        else
                return -EINVAL;
 
        // setup PLL filter
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                filter = 0;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                filter = 0;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                filter = 1;
                break;
 
@@ -763,7 +765,7 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
 
        // calculate divisor
        // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
-       tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
+       tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
 
        // setup tuner buffer
        tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
index ca02e97221721e1f1927ed5b76a9ff29ed523665..98e524178765bb3c1e6094e43fb7edda621fe3ac 100644 (file)
@@ -193,7 +193,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
        dev->input_phys = budget_ci->ir.phys;
        dev->input_id.bustype = BUS_PCI;
        dev->input_id.version = 1;
-       dev->scanmask = 0xff;
        if (saa->pci->subsystem_vendor) {
                dev->input_id.vendor = saa->pci->subsystem_vendor;
                dev->input_id.product = saa->pci->subsystem_device;
@@ -234,6 +233,8 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                dev->map_name = RC_MAP_BUDGET_CI_OLD;
                break;
        }
+       if (!budget_ci->ir.full_rc5)
+               dev->scanmask = 0xff;
 
        error = rc_register_device(dev);
        if (error) {
@@ -659,33 +660,33 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
        return 0;
 }
 
-static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
-                                          struct dvb_frontend_parameters *params)
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u32 div;
        u8 buf[4];
        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
+       if ((p->frequency < 950000) || (p->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (500 - 1)) / 500;    // round correctly
+       div = (p->frequency + (500 - 1)) / 500; /* round correctly */
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
        buf[3] = 0x20;
 
-       if (params->u.qpsk.symbol_rate < 4000000)
+       if (p->symbol_rate < 4000000)
                buf[3] |= 1;
 
-       if (params->frequency < 1250000)
+       if (p->frequency < 1250000)
                buf[3] |= 0;
-       else if (params->frequency < 1550000)
+       else if (p->frequency < 1550000)
                buf[3] |= 0x40;
-       else if (params->frequency < 2050000)
+       else if (p->frequency < 2050000)
                buf[3] |= 0x80;
-       else if (params->frequency < 2150000)
+       else if (p->frequency < 2150000)
                buf[3] |= 0xC0;
 
        if (fe->ops.i2c_gate_ctrl)
@@ -740,8 +741,9 @@ static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 tuner_buf[4];
        struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
@@ -749,7 +751,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
        u8 band, cp, filter;
 
        // determine charge pump
-       tuner_frequency = params->frequency + 36130000;
+       tuner_frequency = p->frequency + 36130000;
        if (tuner_frequency < 87000000)
                return -EINVAL;
        else if (tuner_frequency < 130000000)
@@ -774,30 +776,30 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
                return -EINVAL;
 
        // determine band
-       if (params->frequency < 49000000)
+       if (p->frequency < 49000000)
                return -EINVAL;
-       else if (params->frequency < 159000000)
+       else if (p->frequency < 159000000)
                band = 1;
-       else if (params->frequency < 444000000)
+       else if (p->frequency < 444000000)
                band = 2;
-       else if (params->frequency < 861000000)
+       else if (p->frequency < 861000000)
                band = 4;
        else
                return -EINVAL;
 
        // setup PLL filter and TDA9889
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (p->bandwidth_hz) {
+       case 6000000:
                tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 0;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                tda1004x_writereg(fe, 0x0C, 0x80);
                filter = 0;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 1;
                break;
@@ -808,7 +810,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
 
        // calculate divisor
        // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
-       tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
+       tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
 
        // setup tuner buffer
        tuner_buf[0] = tuner_frequency >> 8;
@@ -855,8 +857,9 @@ static struct tda1004x_config philips_tdm1316l_config_invert = {
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 tuner_buf[5];
        struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
@@ -867,7 +870,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
        u8 band, cp, filter;
 
        // determine charge pump
-       tuner_frequency = params->frequency + 36125000;
+       tuner_frequency = p->frequency + 36125000;
        if (tuner_frequency < 87000000)
                return -EINVAL;
        else if (tuner_frequency < 130000000) {
@@ -904,7 +907,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
        filter = 1;
 
        // calculate divisor
-       tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+       tuner_frequency = (p->frequency + 36125000 + (62500/2)) / 62500;
 
        // setup tuner buffer
        tuner_buf[0] = tuner_frequency >> 8;
index 3395d1a9051699c64f9a67fe6f173d415aff0d22..2cb35c23d2ac890e212a9c8bee34a91a197f8443 100644 (file)
@@ -261,19 +261,25 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c
        return 0;
 }
 
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
        u8 pwr = 0;
        u8 buf[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       u32 div = (params->frequency + 479500) / 125;
-
-       if (params->frequency > 2000000) pwr = 3;
-       else if (params->frequency > 1800000) pwr = 2;
-       else if (params->frequency > 1600000) pwr = 1;
-       else if (params->frequency > 1200000) pwr = 0;
-       else if (params->frequency >= 1100000) pwr = 1;
+       u32 div = (p->frequency + 479500) / 125;
+
+       if (p->frequency > 2000000)
+               pwr = 3;
+       else if (p->frequency > 1800000)
+               pwr = 2;
+       else if (p->frequency > 1600000)
+               pwr = 1;
+       else if (p->frequency > 1200000)
+               pwr = 0;
+       else if (p->frequency >= 1100000)
+               pwr = 1;
        else pwr = 2;
 
        buf[0] = (div >> 8) & 0x7f;
@@ -297,14 +303,15 @@ static struct ves1x93_config alps_bsrv2_config = {
        .invert_pwm = 0,
 };
 
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = params->frequency / 125;
+       div = p->frequency / 125;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x8e;
index d238fb9371a70723e3577f0a3488a7dcf4ea45d7..b21bcce667088a2d0f09cf66cab7d9985a72427b 100644 (file)
@@ -200,19 +200,25 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
        return 0;
 }
 
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u8 pwr = 0;
        u8 buf[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       u32 div = (params->frequency + 479500) / 125;
-
-       if (params->frequency > 2000000) pwr = 3;
-       else if (params->frequency > 1800000) pwr = 2;
-       else if (params->frequency > 1600000) pwr = 1;
-       else if (params->frequency > 1200000) pwr = 0;
-       else if (params->frequency >= 1100000) pwr = 1;
+       u32 div = (c->frequency + 479500) / 125;
+
+       if (c->frequency > 2000000)
+               pwr = 3;
+       else if (c->frequency > 1800000)
+               pwr = 2;
+       else if (c->frequency > 1600000)
+               pwr = 1;
+       else if (c->frequency > 1200000)
+               pwr = 0;
+       else if (c->frequency >= 1100000)
+               pwr = 1;
        else pwr = 2;
 
        buf[0] = (div >> 8) & 0x7f;
@@ -236,19 +242,20 @@ static struct ves1x93_config alps_bsrv2_config =
        .invert_pwm = 0,
 };
 
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (params->frequency + 35937500 + 31250) / 62500;
+       div = (c->frequency + 35937500 + 31250) / 62500;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x85 | ((div >> 10) & 0x60);
-       data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+       data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -263,8 +270,9 @@ static struct ves1820_config alps_tdbe2_config = {
        .selagc = VES1820_SELAGC_SIGNAMPERR,
 };
 
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget *budget = fe->dvb->priv;
        u8 *tuner_addr = fe->tuner_priv;
        u32 div;
@@ -277,19 +285,27 @@ static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dv
        else
                msg.addr = 0x61;
 
-       div = (36125000 + params->frequency) / 166666;
+       div = (36125000 + c->frequency) / 166666;
 
        cfg = 0x88;
 
-       if (params->frequency < 175000000) cpump = 2;
-       else if (params->frequency < 390000000) cpump = 1;
-       else if (params->frequency < 470000000) cpump = 2;
-       else if (params->frequency < 750000000) cpump = 1;
-       else cpump = 3;
+       if (c->frequency < 175000000)
+               cpump = 2;
+       else if (c->frequency < 390000000)
+               cpump = 1;
+       else if (c->frequency < 470000000)
+               cpump = 2;
+       else if (c->frequency < 750000000)
+               cpump = 1;
+       else
+               cpump = 3;
 
-       if (params->frequency < 175000000) band_select = 0x0e;
-       else if (params->frequency < 470000000) band_select = 0x05;
-       else band_select = 0x03;
+       if (c->frequency < 175000000)
+               band_select = 0x0e;
+       else if (c->frequency < 470000000)
+               band_select = 0x05;
+       else
+               band_select = 0x03;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
@@ -312,14 +328,15 @@ static struct l64781_config grundig_29504_401_config_activy = {
 
 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)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = params->frequency / 125;
+       div = c->frequency / 125;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x8e;
@@ -335,14 +352,15 @@ static struct tda8083_config grundig_29504_451_config = {
        .demod_address = 0x68,
 };
 
-static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = params->frequency / 1000;
+       div = c->frequency / 1000;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0xc2;
index e90192fdde1106447daa654f494e5cad91628f2b..5b682cc4c814e99501c45f82ea17171029301183 100644 (file)
@@ -1017,19 +1017,20 @@ static u32 functionality(struct i2c_adapter *adapter)
 
 
 
-static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdmb7_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 data[4];
        struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };
        u32 div;
 
-       div = (params->frequency + 36166667) / 166667;
+       div = (p->frequency + 36166667) / 166667;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = ((div >> 10) & 0x60) | 0x85;
-       data[3] = params->frequency < 592000000 ? 0x40 : 0x80;
+       data[3] = p->frequency < 592000000 ? 0x40 : 0x80;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1071,8 +1072,9 @@ static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 tuner_buf[4];
        struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
@@ -1080,7 +1082,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
        u8 band, cp, filter;
 
        // determine charge pump
-       tuner_frequency = params->frequency + 36130000;
+       tuner_frequency = p->frequency + 36130000;
        if (tuner_frequency < 87000000) return -EINVAL;
        else if (tuner_frequency < 130000000) cp = 3;
        else if (tuner_frequency < 160000000) cp = 5;
@@ -1094,25 +1096,29 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
        else return -EINVAL;
 
        // determine band
-       if (params->frequency < 49000000) return -EINVAL;
-       else if (params->frequency < 159000000) band = 1;
-       else if (params->frequency < 444000000) band = 2;
-       else if (params->frequency < 861000000) band = 4;
+       if (p->frequency < 49000000)
+               return -EINVAL;
+       else if (p->frequency < 159000000)
+               band = 1;
+       else if (p->frequency < 444000000)
+               band = 2;
+       else if (p->frequency < 861000000)
+               band = 4;
        else return -EINVAL;
 
        // setup PLL filter
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (p->bandwidth_hz) {
+       case 6000000:
                tda1004x_writereg(fe, 0x0C, 0);
                filter = 0;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                tda1004x_writereg(fe, 0x0C, 0);
                filter = 0;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                tda1004x_writereg(fe, 0x0C, 0xFF);
                filter = 1;
                break;
@@ -1123,7 +1129,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
 
        // calculate divisor
        // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
-       tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
+       tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
 
        // setup tuner buffer
        tuner_buf[0] = tuner_frequency >> 8;
@@ -1273,23 +1279,24 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
        return 0;
 }
 
-static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
+       if ((p->frequency < 950000) || (p->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (125 - 1)) / 125;    // round correctly
+       div = (p->frequency + (125 - 1)) / 125; /* round correctly */
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
        buf[3] = 0xC4;
 
-       if (params->frequency > 1530000)
+       if (p->frequency > 1530000)
                buf[3] = 0xC0;
 
        /* BSBE1 wants XCE bit set */
@@ -1316,14 +1323,15 @@ static struct stv0299_config alps_stv0299_config = {
        .set_symbol_rate = alps_stv0299_set_symbol_rate,
 };
 
-static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
-       div = params->frequency / 125;
+       div = p->frequency / 125;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
@@ -1343,19 +1351,20 @@ static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
        .demod_address = 0x68,
 };
 
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb* ttusb = fe->dvb->priv;
        u32 div;
        u8 data[4];
        struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
 
-       div = (params->frequency + 35937500 + 31250) / 62500;
+       div = (p->frequency + 35937500 + 31250) / 62500;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
        data[2] = 0x85 | ((div >> 10) & 0x60);
-       data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+       data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1387,8 +1396,9 @@ static u8 read_pwm(struct ttusb* ttusb)
 }
 
 
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
        u8 tuner_buf[5];
        struct i2c_msg tuner_msg = {.addr = 0x60,
@@ -1399,7 +1409,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
        u8 band, cp, filter;
 
        // determine charge pump
-       tuner_frequency = params->frequency;
+       tuner_frequency = p->frequency;
        if      (tuner_frequency <  87000000) {return -EINVAL;}
        else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
        else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
@@ -1417,7 +1427,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
 
        // calculate divisor
        // (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
-       tuner_frequency = ((params->frequency + 36125000) / 62500);
+       tuner_frequency = ((p->frequency + 36125000) / 62500);
 
        // setup tuner buffer
        tuner_buf[0] = tuner_frequency >> 8;
@@ -1694,10 +1704,8 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        ttusb->i2c_adap.dev.parent        = &udev->dev;
 
        result = i2c_add_adapter(&ttusb->i2c_adap);
-       if (result) {
-               dvb_unregister_adapter (&ttusb->adapter);
-               return result;
-       }
+       if (result)
+               goto err_unregister_adapter;
 
        memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
 
@@ -1714,33 +1722,29 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
        ttusb->dvb_demux.write_to_decoder = NULL;
 
-       if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
+       result = dvb_dmx_init(&ttusb->dvb_demux);
+       if (result < 0) {
                printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
-               i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (&ttusb->adapter);
-               return -ENODEV;
+               result = -ENODEV;
+               goto err_i2c_del_adapter;
        }
 //FIXME dmxdev (nur WAS?)
        ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
        ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
        ttusb->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) {
+       result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter);
+       if (result < 0) {
                printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
                       result);
-               dvb_dmx_release(&ttusb->dvb_demux);
-               i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (&ttusb->adapter);
-               return -ENODEV;
+               result = -ENODEV;
+               goto err_release_dmx;
        }
 
        if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
                printk("ttusb_dvb: dvb_net_init failed!\n");
-               dvb_dmxdev_release(&ttusb->dmxdev);
-               dvb_dmx_release(&ttusb->dvb_demux);
-               i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (&ttusb->adapter);
-               return -ENODEV;
+               result = -ENODEV;
+               goto err_release_dmxdev;
        }
 
        usb_set_intfdata(intf, (void *) ttusb);
@@ -1748,6 +1752,16 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        frontend_init(ttusb);
 
        return 0;
+
+err_release_dmxdev:
+       dvb_dmxdev_release(&ttusb->dmxdev);
+err_release_dmx:
+       dvb_dmx_release(&ttusb->dvb_demux);
+err_i2c_del_adapter:
+       i2c_del_adapter(&ttusb->i2c_adap);
+err_unregister_adapter:
+       dvb_unregister_adapter (&ttusb->adapter);
+       return result;
 }
 
 static void ttusb_disconnect(struct usb_interface *intf)
index 21260aad1e54684a46c82248dc0bee8681327c21..5c45c9d0712ddf949f0ac571b5649111585046ae 100644 (file)
@@ -87,8 +87,9 @@ static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
        return 0;
 }
 
-static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
        u8 b[] = { 0x00, 0x00, 0x00, 0x03,
                   0x00, 0x00, 0x00, 0x00,
@@ -113,8 +114,9 @@ static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
                return 0;
 }
 
-static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 
        u8 b[] = { 0x00, 0x00, 0x00, 0x01,
@@ -135,7 +137,7 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron
        freq = htonl(p->frequency +
               (state->hi_band ? LOF_HI : LOF_LO));
        memcpy(&b[4], &freq, sizeof(u32));
-       sym_rate = htonl(p->u.qam.symbol_rate);
+       sym_rate = htonl(p->symbol_rate);
        memcpy(&b[12], &sym_rate, sizeof(u32));
        band = htonl(state->hi_band ? LOF_HI : LOF_LO);
        memcpy(&b[24], &band, sizeof(u32));
@@ -241,10 +243,9 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
 }
 
 static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
-
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "TechnoTrend/Hauppauge DEC2000-t Frontend",
-               .type                   = FE_OFDM,
                .frequency_min          = 51000000,
                .frequency_max          = 858000000,
                .frequency_stepsize     = 62500,
@@ -265,10 +266,9 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
 };
 
 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
-
+       .delsys = { SYS_DVBS },
        .info = {
                .name                   = "TechnoTrend/Hauppauge DEC3000-s Frontend",
-               .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
                .frequency_stepsize     = 125,
index 6edc9ba81203698e9948c066ddfac2370a142b1d..6f9eb94e85b387f78f144fd74c244e0e0859237a 100644 (file)
@@ -108,8 +108,7 @@ static long media_device_enum_entities(struct media_device *mdev,
        u_ent.group_id = ent->group_id;
        u_ent.pads = ent->num_pads;
        u_ent.links = ent->num_links - ent->num_backlinks;
-       u_ent.v4l.major = ent->v4l.major;
-       u_ent.v4l.minor = ent->v4l.minor;
+       memcpy(&u_ent.raw, &ent->info, sizeof(ent->info));
        if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
                return -EFAULT;
        return 0;
index ccd5f0d8a012113a08b788b9927860079289fa0c..e954781c90bfd920e57bea52d1a1fa2c34f8a151 100644 (file)
@@ -11,6 +11,162 @@ menuconfig RADIO_ADAPTERS
 
 if RADIO_ADAPTERS && VIDEO_V4L2
 
+config RADIO_SI470X
+       bool "Silicon Labs Si470x FM Radio Receiver support"
+       depends on VIDEO_V4L2
+
+source "drivers/media/radio/si470x/Kconfig"
+
+config USB_MR800
+       tristate "AverMedia MR 800 USB FM radio support"
+       depends on USB && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to connect this type of radio to your
+         computer's USB port. Note that the audio is not digital, and
+         you must connect the line out connector to a sound card or a
+         set of speakers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-mr800.
+
+config USB_DSBR
+       tristate "D-Link/GemTek USB FM radio support"
+       depends on USB && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to connect this type of radio to your
+         computer's USB port. Note that the audio is not digital, and
+         you must connect the line out connector to a sound card or a
+         set of speakers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called dsbr100.
+
+config RADIO_MAXIRADIO
+       tristate "Guillemot MAXI Radio FM 2000 radio"
+       depends on VIDEO_V4L2 && PCI
+       ---help---
+         Choose Y here if you have this radio card.  This card may also be
+         found as Gemtek PCI FM.
+
+         In order to control your radio card, you will need to use programs
+         that are compatible with the Video For Linux API.  Information on
+         this API and pointers to "v4l" programs may be found at
+         <file:Documentation/video4linux/API.html>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-maxiradio.
+
+
+config I2C_SI4713
+       tristate "I2C driver for Silicon Labs Si4713 device"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         Say Y here if you want support to Si4713 I2C device.
+         This device driver supports only i2c bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called si4713.
+
+config RADIO_SI4713
+       tristate "Silicon Labs Si4713 FM Radio Transmitter support"
+       depends on I2C && VIDEO_V4L2
+       select I2C_SI4713
+       ---help---
+         Say Y here if you want support to Si4713 FM Radio Transmitter.
+         This device can transmit audio through FM. It can transmit
+         RDS and RBDS signals as well. This module is the v4l2 radio
+         interface for the i2c driver of this device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-si4713.
+
+config RADIO_TEA5764
+       tristate "TEA5764 I2C FM radio support"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to use the TEA5764 FM chip found in
+         EZX phones. This FM chip is present in EZX phones from Motorola,
+         connected to internal pxa I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-tea5764.
+
+config RADIO_TEA5764_XTAL
+       bool "TEA5764 crystal reference"
+       depends on RADIO_TEA5764=y
+       default y
+       help
+         Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
+         here if TEA5764 reference frequency is connected in FREQIN.
+
+config RADIO_SAA7706H
+       tristate "SAA7706H Car Radio DSP"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to use the SAA7706H Car radio Digital
+         Signal Processor, found for instance on the Russellville development
+         board. On the russellville the device is connected to internal
+         timberdale I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called SAA7706H.
+
+config RADIO_TEF6862
+       tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to use the TEF6862 Car Radio Enhanced
+         Selectivity Tuner, found for instance on the Russellville development
+         board. On the russellville the device is connected to internal
+         timberdale I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called TEF6862.
+
+config RADIO_TIMBERDALE
+       tristate "Enable the Timberdale radio driver"
+       depends on MFD_TIMBERDALE && VIDEO_V4L2
+       depends on I2C  # for RADIO_SAA7706H
+       select RADIO_TEF6862
+       select RADIO_SAA7706H
+       ---help---
+         This is a kind of umbrella driver for the Radio Tuner and DSP
+         found behind the Timberdale FPGA on the Russellville board.
+         Enabling this driver will automatically select the DSP and tuner.
+
+config RADIO_WL1273
+       tristate "Texas Instruments WL1273 I2C FM Radio"
+       depends on I2C && VIDEO_V4L2
+       select MFD_CORE
+       select MFD_WL1273_CORE
+       select FW_LOADER
+       ---help---
+         Choose Y here if you have this FM radio chip.
+
+         In order to control your radio card, you will need to use programs
+         that are compatible with the Video For Linux 2 API.  Information on
+         this API and pointers to "v4l2" programs may be found at
+         <file:Documentation/video4linux/API.html>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-wl1273.
+
+# TI's ST based wl128x FM radio
+source "drivers/media/radio/wl128x/Kconfig"
+
+#
+# ISA drivers configuration
+#
+
+menuconfig V4L_RADIO_ISA_DRIVERS
+       bool "ISA radio devices"
+       depends on ISA
+       default n
+       ---help---
+         Say Y here to enable support for these ISA drivers.
+
+if V4L_RADIO_ISA_DRIVERS
+
 config RADIO_CADET
        tristate "ADS Cadet AM/FM Tuner"
        depends on ISA && VIDEO_V4L2
@@ -151,21 +307,6 @@ config RADIO_GEMTEK_PROBE
          following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
          0x28c.
 
-config RADIO_MAXIRADIO
-       tristate "Guillemot MAXI Radio FM 2000 radio"
-       depends on VIDEO_V4L2 && PCI
-       ---help---
-         Choose Y here if you have this radio card.  This card may also be
-         found as Gemtek PCI FM.
-
-         In order to control your radio card, you will need to use programs
-         that are compatible with the Video For Linux API.  Information on
-         this API and pointers to "v4l" programs may be found at
-         <file:Documentation/video4linux/API.html>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called radio-maxiradio.
-
 config RADIO_MIROPCM20
        tristate "miroSOUND PCM20 radio"
        depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
@@ -316,130 +457,6 @@ config RADIO_ZOLTRIX_PORT
        help
          Enter the I/O port of your Zoltrix radio card.
 
-config I2C_SI4713
-       tristate "I2C driver for Silicon Labs Si4713 device"
-       depends on I2C && VIDEO_V4L2
-       ---help---
-         Say Y here if you want support to Si4713 I2C device.
-         This device driver supports only i2c bus.
-
-         To compile this driver as a module, choose M here: the
-         module will be called si4713.
-
-config RADIO_SI4713
-       tristate "Silicon Labs Si4713 FM Radio Transmitter support"
-       depends on I2C && VIDEO_V4L2
-       select I2C_SI4713
-       ---help---
-         Say Y here if you want support to Si4713 FM Radio Transmitter.
-         This device can transmit audio through FM. It can transmit
-         RDS and RBDS signals as well. This module is the v4l2 radio
-         interface for the i2c driver of this device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called radio-si4713.
-
-config USB_DSBR
-       tristate "D-Link/GemTek USB FM radio support"
-       depends on USB && VIDEO_V4L2
-       ---help---
-         Say Y here if you want to connect this type of radio to your
-         computer's USB port. Note that the audio is not digital, and
-         you must connect the line out connector to a sound card or a
-         set of speakers.
-
-         To compile this driver as a module, choose M here: the
-         module will be called dsbr100.
-
-config RADIO_SI470X
-       bool "Silicon Labs Si470x FM Radio Receiver support"
-       depends on VIDEO_V4L2
-
-source "drivers/media/radio/si470x/Kconfig"
-
-config USB_MR800
-       tristate "AverMedia MR 800 USB FM radio support"
-       depends on USB && VIDEO_V4L2
-       ---help---
-         Say Y here if you want to connect this type of radio to your
-         computer's USB port. Note that the audio is not digital, and
-         you must connect the line out connector to a sound card or a
-         set of speakers.
-
-         To compile this driver as a module, choose M here: the
-         module will be called radio-mr800.
-
-config RADIO_TEA5764
-       tristate "TEA5764 I2C FM radio support"
-       depends on I2C && VIDEO_V4L2
-       ---help---
-         Say Y here if you want to use the TEA5764 FM chip found in
-         EZX phones. This FM chip is present in EZX phones from Motorola,
-         connected to internal pxa I2C bus.
-
-         To compile this driver as a module, choose M here: the
-         module will be called radio-tea5764.
-
-config RADIO_TEA5764_XTAL
-       bool "TEA5764 crystal reference"
-       depends on RADIO_TEA5764=y
-       default y
-       help
-         Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
-         here if TEA5764 reference frequency is connected in FREQIN.
-
-config RADIO_SAA7706H
-       tristate "SAA7706H Car Radio DSP"
-       depends on I2C && VIDEO_V4L2
-       ---help---
-         Say Y here if you want to use the SAA7706H Car radio Digital
-         Signal Processor, found for instance on the Russellville development
-         board. On the russellville the device is connected to internal
-         timberdale I2C bus.
-
-         To compile this driver as a module, choose M here: the
-         module will be called SAA7706H.
-
-config RADIO_TEF6862
-       tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
-       depends on I2C && VIDEO_V4L2
-       ---help---
-         Say Y here if you want to use the TEF6862 Car Radio Enhanced
-         Selectivity Tuner, found for instance on the Russellville development
-         board. On the russellville the device is connected to internal
-         timberdale I2C bus.
-
-         To compile this driver as a module, choose M here: the
-         module will be called TEF6862.
-
-config RADIO_TIMBERDALE
-       tristate "Enable the Timberdale radio driver"
-       depends on MFD_TIMBERDALE && VIDEO_V4L2
-       depends on I2C  # for RADIO_SAA7706H
-       select RADIO_TEF6862
-       select RADIO_SAA7706H
-       ---help---
-         This is a kind of umbrella driver for the Radio Tuner and DSP
-         found behind the Timberdale FPGA on the Russellville board.
-         Enabling this driver will automatically select the DSP and tuner.
-
-config RADIO_WL1273
-       tristate "Texas Instruments WL1273 I2C FM Radio"
-       depends on I2C && VIDEO_V4L2
-       select MFD_WL1273_CORE
-       select FW_LOADER
-       ---help---
-         Choose Y here if you have this FM radio chip.
-
-         In order to control your radio card, you will need to use programs
-         that are compatible with the Video For Linux 2 API.  Information on
-         this API and pointers to "v4l2" programs may be found at
-         <file:Documentation/video4linux/API.html>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called radio-wl1273.
-
-# TI's ST based wl128x FM radio
-source "drivers/media/radio/wl128x/Kconfig"
+endif # V4L_RADIO_ISA_DRIVERS
 
 endif # RADIO_ADAPTERS
index d1fab58850612a333fea3a5f26603bf04c52bc90..c54210c7fef90783200ccec467230fa6a7f3dc69 100644 (file)
@@ -355,17 +355,4 @@ static struct platform_driver radio_si4713_pdriver = {
        .remove         = __exit_p(radio_si4713_pdriver_remove),
 };
 
-/* Module Interface */
-static int __init radio_si4713_module_init(void)
-{
-       return platform_driver_register(&radio_si4713_pdriver);
-}
-
-static void __exit radio_si4713_module_exit(void)
-{
-       platform_driver_unregister(&radio_si4713_pdriver);
-}
-
-module_init(radio_si4713_module_init);
-module_exit(radio_si4713_module_exit);
-
+module_platform_driver(radio_si4713_pdriver);
index 3e9209f84e09bb04f46e75e2e517f10f9d37f608..5d9a90ac3a1c0230b75bffaeff6de7f4cfbb015c 100644 (file)
@@ -226,20 +226,7 @@ static struct platform_driver timbradio_platform_driver = {
        .remove         = timbradio_remove,
 };
 
-/*--------------------------------------------------------------------------*/
-
-static int __init timbradio_init(void)
-{
-       return platform_driver_register(&timbradio_platform_driver);
-}
-
-static void __exit timbradio_exit(void)
-{
-       platform_driver_unregister(&timbradio_platform_driver);
-}
-
-module_init(timbradio_init);
-module_exit(timbradio_exit);
+module_platform_driver(timbradio_platform_driver);
 
 MODULE_DESCRIPTION("Timberdale Radio driver");
 MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
index 8aa4968d57bc6cf3317669fb3a8b9c27daf074b4..f1b607099b6c10361a1305c521b612d7c10ca8ff 100644 (file)
@@ -2148,8 +2148,6 @@ pdata_err:
        return r;
 }
 
-MODULE_ALIAS("platform:wl1273_fm_radio");
-
 static struct platform_driver wl1273_fm_radio_driver = {
        .probe          = wl1273_fm_radio_probe,
        .remove         = __devexit_p(wl1273_fm_radio_remove),
@@ -2159,20 +2157,9 @@ static struct platform_driver wl1273_fm_radio_driver = {
        },
 };
 
-static int __init wl1273_fm_module_init(void)
-{
-       pr_info("%s\n", __func__);
-       return platform_driver_register(&wl1273_fm_radio_driver);
-}
-module_init(wl1273_fm_module_init);
-
-static void __exit wl1273_fm_module_exit(void)
-{
-       platform_driver_unregister(&wl1273_fm_radio_driver);
-       pr_info(DRIVER_DESC ", Exiting.\n");
-}
-module_exit(wl1273_fm_module_exit);
+module_platform_driver(wl1273_fm_radio_driver);
 
 MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wl1273_fm_radio");
index 0991e1973678ce0751c455cb85249264935415fb..3408685b690c74406b690ea101992563028169f1 100644 (file)
@@ -118,9 +118,11 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
        i2cmsg[2] = pll & 0xff;
 
        err = i2c_master_send(client, i2cmsg, sizeof(i2cmsg));
-       if (!err)
-               state->freq = f->frequency;
-       return err;
+       if (err != sizeof(i2cmsg))
+               return err < 0 ? err : -EIO;
+
+       state->freq = f->frequency;
+       return 0;
 }
 
 static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
index 749f67b192e7818340126d5582628ce779d865f3..86b28579f0c745a4e257b00aecb26ce320a3339f 100644 (file)
@@ -5,7 +5,7 @@ menu "Texas Instruments WL128x FM driver (ST based)"
 config RADIO_WL128X
        tristate "Texas Instruments WL128x FM Radio"
        depends on VIDEO_V4L2 && RFKILL
-       select TI_ST
+       select TI_ST if NET && GPIOLIB
        help
        Choose Y here if you have this FM radio chip.
 
index 5991ab60303dcafda387ce7d6d304ef039aa39db..bf867a6b5ea0b5c745bf6684a75183e25b354843 100644 (file)
@@ -387,7 +387,7 @@ static void send_tasklet(unsigned long arg)
  * Queues FM Channel-8 packet to FM TX queue and schedules FM TX tasklet for
  * transmission
  */
-static u32 fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type,        void *payload,
+static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type,        void *payload,
                int payload_len, struct completion *wait_completion)
 {
        struct sk_buff *skb;
@@ -456,13 +456,13 @@ static u32 fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type,   void *payload,
 }
 
 /* Sends FM Channel-8 command to the chip and waits for the response */
-u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
+int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
                unsigned int payload_len, void *response, int *response_len)
 {
        struct sk_buff *skb;
        struct fm_event_msg_hdr *evt_hdr;
        unsigned long flags;
-       u32 ret;
+       int ret;
 
        init_completion(&fmdev->maintask_comp);
        ret = fm_send_cmd(fmdev, fm_op, type, payload, payload_len,
@@ -470,8 +470,8 @@ u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
        if (ret)
                return ret;
 
-       ret = wait_for_completion_timeout(&fmdev->maintask_comp, FM_DRV_TX_TIMEOUT);
-       if (!ret) {
+       if (!wait_for_completion_timeout(&fmdev->maintask_comp,
+                                        FM_DRV_TX_TIMEOUT)) {
                fmerr("Timeout(%d sec),didn't get reg"
                           "completion signal from RX tasklet\n",
                           jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
@@ -508,7 +508,7 @@ u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
 }
 
 /* --- Helper functions used in FM interrupt handlers ---*/
-static inline u32 check_cmdresp_status(struct fmdev *fmdev,
+static inline int check_cmdresp_status(struct fmdev *fmdev,
                struct sk_buff **skb)
 {
        struct fm_event_msg_hdr *fm_evt_hdr;
@@ -1058,7 +1058,7 @@ static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *fmdev)
 }
 
 /* Returns availability of RDS data in internel buffer */
-u32 fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
+int fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
                                struct poll_table_struct *pts)
 {
        poll_wait(file, &fmdev->rx.rds.read_queue, pts);
@@ -1069,7 +1069,7 @@ u32 fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
 }
 
 /* Copies RDS data from internal buffer to user buffer */
-u32 fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
+int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
                u8 __user *buf, size_t count)
 {
        u32 block_count;
@@ -1113,7 +1113,7 @@ u32 fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
        return ret;
 }
 
-u32 fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+int fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
 {
        switch (fmdev->curr_fmmode) {
        case FM_MODE_RX:
@@ -1127,7 +1127,7 @@ u32 fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
        }
 }
 
-u32 fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
+int fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
 {
        if (fmdev->rx.freq == FM_UNDEFINED_FREQ) {
                fmerr("RX frequency is not set\n");
@@ -1153,7 +1153,7 @@ u32 fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
 
 }
 
-u32 fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
+int fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
 {
        switch (fmdev->curr_fmmode) {
        case FM_MODE_RX:
@@ -1167,7 +1167,7 @@ u32 fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
        }
 }
 
-u32 fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
 {
        switch (fmdev->curr_fmmode) {
        case FM_MODE_RX:
@@ -1181,7 +1181,7 @@ u32 fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
        }
 }
 
-u32 fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
 {
        switch (fmdev->curr_fmmode) {
        case FM_MODE_RX:
@@ -1195,7 +1195,7 @@ u32 fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
        }
 }
 
-u32 fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
 {
        switch (fmdev->curr_fmmode) {
        case FM_MODE_RX:
@@ -1210,10 +1210,10 @@ u32 fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
 }
 
 /* Sends power off command to the chip */
-static u32 fm_power_down(struct fmdev *fmdev)
+static int fm_power_down(struct fmdev *fmdev)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
                fmerr("FM core is not ready\n");
@@ -1234,7 +1234,7 @@ static u32 fm_power_down(struct fmdev *fmdev)
 }
 
 /* Reads init command from FM firmware file and loads to the chip */
-static u32 fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
+static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
 {
        const struct firmware *fw_entry;
        struct bts_header *fw_header;
@@ -1299,7 +1299,7 @@ rel_fw:
 }
 
 /* Loads default RX configuration to the chip */
-static u32 load_default_rx_configuration(struct fmdev *fmdev)
+static int load_default_rx_configuration(struct fmdev *fmdev)
 {
        int ret;
 
@@ -1311,7 +1311,7 @@ static u32 load_default_rx_configuration(struct fmdev *fmdev)
 }
 
 /* Does FM power on sequence */
-static u32 fm_power_up(struct fmdev *fmdev, u8 mode)
+static int fm_power_up(struct fmdev *fmdev, u8 mode)
 {
        u16 payload, asic_id, asic_ver;
        int resp_len, ret;
@@ -1374,7 +1374,7 @@ rel:
 }
 
 /* Set FM Modes(TX, RX, OFF) */
-u32 fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
+int fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
 {
        int ret = 0;
 
@@ -1427,7 +1427,7 @@ u32 fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
 }
 
 /* Returns current FM mode (TX, RX, OFF) */
-u32 fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
+int fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
 {
        if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
                fmerr("FM core is not ready\n");
@@ -1483,10 +1483,10 @@ static void fm_st_reg_comp_cb(void *arg, char data)
  * This function will be called from FM V4L2 open function.
  * Register with ST driver and initialize driver data.
  */
-u32 fmc_prepare(struct fmdev *fmdev)
+int fmc_prepare(struct fmdev *fmdev)
 {
        static struct st_proto_s fm_st_proto;
-       u32 ret;
+       int ret;
 
        if (test_bit(FM_CORE_READY, &fmdev->flag)) {
                fmdbg("FM Core is already up\n");
@@ -1512,10 +1512,8 @@ u32 fmc_prepare(struct fmdev *fmdev)
                fmdev->streg_cbdata = -EINPROGRESS;
                fmdbg("%s waiting for ST reg completion signal\n", __func__);
 
-               ret = wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
-                               FM_ST_REG_TIMEOUT);
-
-               if (!ret) {
+               if (!wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
+                                                FM_ST_REG_TIMEOUT)) {
                        fmerr("Timeout(%d sec), didn't get reg "
                                        "completion signal from ST\n",
                                        jiffies_to_msecs(FM_ST_REG_TIMEOUT) / 1000);
@@ -1589,10 +1587,10 @@ u32 fmc_prepare(struct fmdev *fmdev)
  * This function will be called from FM V4L2 release function.
  * Unregister from ST driver.
  */
-u32 fmc_release(struct fmdev *fmdev)
+int fmc_release(struct fmdev *fmdev)
 {
        static struct st_proto_s fm_st_proto;
-       u32 ret;
+       int ret;
 
        if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
                fmdbg("FM Core is already down\n");
@@ -1631,7 +1629,7 @@ u32 fmc_release(struct fmdev *fmdev)
 static int __init fm_drv_init(void)
 {
        struct fmdev *fmdev = NULL;
-       u32 ret = -ENOMEM;
+       int ret = -ENOMEM;
 
        fmdbg("FM driver version %s\n", FM_DRV_VERSION);
 
index aee243bb6630d550e018b3f37e2d6d5a986cba9c..d9b9c6cf83b40fe9f9a973ec3de930b784cd5b4d 100644 (file)
@@ -368,27 +368,27 @@ struct fm_event_msg_hdr {
 #define FM_TX_ANT_IMP_500              2
 
 /* Functions exported by FM common sub-module */
-u32 fmc_prepare(struct fmdev *);
-u32 fmc_release(struct fmdev *);
+int fmc_prepare(struct fmdev *);
+int fmc_release(struct fmdev *);
 
 void fmc_update_region_info(struct fmdev *, u8);
-u32 fmc_send_cmd(struct fmdev *, u8, u16,
+int fmc_send_cmd(struct fmdev *, u8, u16,
                                void *, unsigned int, void *, int *);
-u32 fmc_is_rds_data_available(struct fmdev *, struct file *,
+int fmc_is_rds_data_available(struct fmdev *, struct file *,
                                struct poll_table_struct *);
-u32 fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
+int fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
                                        u8 __user *, size_t);
 
-u32 fmc_set_freq(struct fmdev *, u32);
-u32 fmc_set_mode(struct fmdev *, u8);
-u32 fmc_set_region(struct fmdev *, u8);
-u32 fmc_set_mute_mode(struct fmdev *, u8);
-u32 fmc_set_stereo_mono(struct fmdev *, u16);
-u32 fmc_set_rds_mode(struct fmdev *, u8);
+int fmc_set_freq(struct fmdev *, u32);
+int fmc_set_mode(struct fmdev *, u8);
+int fmc_set_region(struct fmdev *, u8);
+int fmc_set_mute_mode(struct fmdev *, u8);
+int fmc_set_stereo_mono(struct fmdev *, u16);
+int fmc_set_rds_mode(struct fmdev *, u8);
 
-u32 fmc_get_freq(struct fmdev *, u32 *);
-u32 fmc_get_region(struct fmdev *, u8 *);
-u32 fmc_get_mode(struct fmdev *, u8 *);
+int fmc_get_freq(struct fmdev *, u32 *);
+int fmc_get_region(struct fmdev *, u8 *);
+int fmc_get_mode(struct fmdev *, u8 *);
 
 /*
  * channel spacing
index ec529b55b040db1de737f0901cb13a222f0c9827..43fb72291bea15551f7bf5ca01577d23db879ef9 100644 (file)
@@ -43,12 +43,13 @@ void fm_rx_reset_station_info(struct fmdev *fmdev)
        fmdev->rx.stat_info.af_list_max = 0;
 }
 
-u32 fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
+int fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
 {
        unsigned long timeleft;
        u16 payload, curr_frq, intr_flag;
        u32 curr_frq_in_khz;
-       u32 ret, resp_len;
+       u32 resp_len;
+       int ret;
 
        if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) {
                fmerr("Invalid frequency %d\n", freq);
@@ -141,10 +142,10 @@ exit:
        return ret;
 }
 
-static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
+static int fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (spacing > 0 && spacing <= 50000)
                spacing = FM_CHANNEL_SPACING_50KHZ;
@@ -165,7 +166,7 @@ static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
        return ret;
 }
 
-u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
+int fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
                u32 wrap_around, u32 spacing)
 {
        u32 resp_len;
@@ -173,7 +174,7 @@ u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
        u16 payload, int_reason, intr_flag;
        u16 offset, space_idx;
        unsigned long timeleft;
-       u32 ret;
+       int ret;
 
        /* Set channel spacing */
        ret = fm_rx_set_channel_spacing(fmdev, spacing);
@@ -296,10 +297,10 @@ again:
        return ret;
 }
 
-u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
+int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -322,7 +323,7 @@ u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
 }
 
 /* Get volume */
-u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
+int fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -338,7 +339,7 @@ u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
 }
 
 /* To get current band's bottom and top frequency */
-u32 fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
+int fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
 {
        if (bot_freq != NULL)
                *bot_freq = fmdev->rx.region.bot_freq;
@@ -356,11 +357,11 @@ void fm_rx_get_region(struct fmdev *fmdev, u8 *region)
 }
 
 /* Sets band (0-Europe/US; 1-Japan) */
-u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
+int fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
 {
        u16 payload;
        u32 new_frq = 0;
-       u32 ret;
+       int ret;
 
        if (region_to_set != FM_BAND_EUROPE_US &&
            region_to_set != FM_BAND_JAPAN) {
@@ -399,7 +400,7 @@ u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
 }
 
 /* Reads current mute mode (Mute Off/On/Attenuate)*/
-u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
+int fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -414,10 +415,10 @@ u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
        return 0;
 }
 
-static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
+static int fm_config_rx_mute_reg(struct fmdev *fmdev)
 {
        u16 payload, muteval;
-       u32 ret;
+       int ret;
 
        muteval = 0;
        switch (fmdev->rx.mute_mode) {
@@ -448,10 +449,10 @@ static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
 }
 
 /* Configures mute mode (Mute Off/On/Attenuate) */
-u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
 {
        u8 org_state;
-       u32 ret;
+       int ret;
 
        if (fmdev->rx.mute_mode == mute_mode_toset)
                return 0;
@@ -469,7 +470,7 @@ u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
 }
 
 /* Gets RF dependent soft mute mode enable/disable status */
-u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
+int fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -485,10 +486,10 @@ u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
 }
 
 /* Sets RF dependent soft mute mode */
-u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
+int fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
 {
        u8 org_state;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -514,11 +515,11 @@ u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
 }
 
 /* Returns the signal strength level of current channel */
-u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
+int fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
 {
        u16 curr_rssi_lel;
        u32 resp_len;
-       u32 ret;
+       int ret;
 
        if (rssilvl == NULL) {
                fmerr("Invalid memory\n");
@@ -539,10 +540,10 @@ u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
  * Sets the signal strength level that once reached
  * will stop the auto search process
  */
-u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
+int fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN ||
                        rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) {
@@ -561,7 +562,7 @@ u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
 }
 
 /* Returns current RX RSSI threshold value */
-u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
+int fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -577,10 +578,10 @@ u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
 }
 
 /* Sets RX stereo/mono modes */
-u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) {
                fmerr("Invalid mode\n");
@@ -605,10 +606,11 @@ u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
 }
 
 /* Gets current RX stereo/mono mode */
-u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
+int fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
 {
        u16 curr_mode;
-       u32 ret, resp_len;
+       u32 resp_len;
+       int ret;
 
        if (mode == NULL) {
                fmerr("Invalid memory\n");
@@ -626,10 +628,10 @@ u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
 }
 
 /* Choose RX de-emphasis filter mode (50us/75us) */
-u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
+int fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -652,7 +654,7 @@ u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
 }
 
 /* Gets current RX de-emphasis filter mode */
-u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
+int fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -668,10 +670,10 @@ u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
 }
 
 /* Enable/Disable RX RDS */
-u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) {
                fmerr("Invalid rds option\n");
@@ -743,7 +745,7 @@ u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
 }
 
 /* Returns current RX RDS enable/disable status */
-u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
+int fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -759,10 +761,10 @@ u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
 }
 
 /* Sets RDS operation mode (RDS/RDBS) */
-u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
+int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -784,7 +786,7 @@ u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
 }
 
 /* Returns current RDS operation mode */
-u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
+int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -800,10 +802,10 @@ u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
 }
 
 /* Configures Alternate Frequency switch mode */
-u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
+int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
@@ -831,7 +833,7 @@ u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
 }
 
 /* Returns Alternate Frequency switch status */
-u32 fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
+int fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
 {
        if (fmdev->curr_fmmode != FM_MODE_RX)
                return -EPERM;
index 329e62f6be76950ba59b8cccbce6bb55900d39a9..32add81f8d87699fd15eafedefa6b8d9a31264b1 100644 (file)
 #ifndef _FMDRV_RX_H
 #define _FMDRV_RX_H
 
-u32 fm_rx_set_freq(struct fmdev *, u32);
-u32 fm_rx_set_mute_mode(struct fmdev *, u8);
-u32 fm_rx_set_stereo_mono(struct fmdev *, u16);
-u32 fm_rx_set_rds_mode(struct fmdev *, u8);
-u32 fm_rx_set_rds_system(struct fmdev *, u8);
-u32 fm_rx_set_volume(struct fmdev *, u16);
-u32 fm_rx_set_rssi_threshold(struct fmdev *, short);
-u32 fm_rx_set_region(struct fmdev *, u8);
-u32 fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
-u32 fm_rx_set_deemphasis_mode(struct fmdev *, u16);
-u32 fm_rx_set_af_switch(struct fmdev *, u8);
+int fm_rx_set_freq(struct fmdev *, u32);
+int fm_rx_set_mute_mode(struct fmdev *, u8);
+int fm_rx_set_stereo_mono(struct fmdev *, u16);
+int fm_rx_set_rds_mode(struct fmdev *, u8);
+int fm_rx_set_rds_system(struct fmdev *, u8);
+int fm_rx_set_volume(struct fmdev *, u16);
+int fm_rx_set_rssi_threshold(struct fmdev *, short);
+int fm_rx_set_region(struct fmdev *, u8);
+int fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
+int fm_rx_set_deemphasis_mode(struct fmdev *, u16);
+int fm_rx_set_af_switch(struct fmdev *, u8);
 
 void fm_rx_reset_rds_cache(struct fmdev *);
 void fm_rx_reset_station_info(struct fmdev *);
 
-u32 fm_rx_seek(struct fmdev *, u32, u32, u32);
+int fm_rx_seek(struct fmdev *, u32, u32, u32);
 
-u32 fm_rx_get_rds_mode(struct fmdev *, u8 *);
-u32 fm_rx_get_rds_system(struct fmdev *, u8 *);
-u32 fm_rx_get_mute_mode(struct fmdev *, u8 *);
-u32 fm_rx_get_volume(struct fmdev *, u16 *);
-u32 fm_rx_get_band_freq_range(struct fmdev *,
+int fm_rx_get_rds_mode(struct fmdev *, u8 *);
+int fm_rx_get_rds_system(struct fmdev *, u8 *);
+int fm_rx_get_mute_mode(struct fmdev *, u8 *);
+int fm_rx_get_volume(struct fmdev *, u16 *);
+int fm_rx_get_band_freq_range(struct fmdev *,
                                        u32 *, u32 *);
-u32 fm_rx_get_stereo_mono(struct fmdev *, u16 *);
-u32 fm_rx_get_rssi_level(struct fmdev *, u16 *);
-u32 fm_rx_get_rssi_threshold(struct fmdev *, short *);
-u32 fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
-u32 fm_rx_get_deemph_mode(struct fmdev *, u16 *);
-u32 fm_rx_get_af_switch(struct fmdev *, u8 *);
+int fm_rx_get_stereo_mono(struct fmdev *, u16 *);
+int fm_rx_get_rssi_level(struct fmdev *, u16 *);
+int fm_rx_get_rssi_threshold(struct fmdev *, short *);
+int fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
+int fm_rx_get_deemph_mode(struct fmdev *, u16 *);
+int fm_rx_get_af_switch(struct fmdev *, u8 *);
 void fm_rx_get_region(struct fmdev *, u8 *);
 
-u32 fm_rx_set_chanl_spacing(struct fmdev *, u8);
-u32 fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
+int fm_rx_set_chanl_spacing(struct fmdev *, u8);
+int fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
 #endif
 
index be54068b56a8b0abd3344896e34c9e43cf60a114..6ea33e09d63b23b306979142ace913d6806f561f 100644 (file)
 #include "fmdrv_common.h"
 #include "fmdrv_tx.h"
 
-u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->tx_data.aud_mode == mode)
                return 0;
@@ -46,10 +46,10 @@ u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
        return ret;
 }
 
-static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text)
+static int set_rds_text(struct fmdev *fmdev, u8 *rds_text)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text,
                        strlen(rds_text), NULL, NULL);
@@ -66,10 +66,10 @@ static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text)
        return 0;
 }
 
-static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode)
+static int set_rds_data_mode(struct fmdev *fmdev, u8 mode)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        /* Setting unique PI TODO: how unique? */
        payload = (u16)0xcafe;
@@ -89,10 +89,10 @@ static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode)
        return 0;
 }
 
-static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
+static int set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        len |= type << 8;
        payload = len;
@@ -105,10 +105,10 @@ static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
        return 0;
 }
 
-u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
 {
        u16 payload;
-       u32 ret;
+       int ret;
        u8 rds_text[] = "Zoom2\n";
 
        fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis,
@@ -148,10 +148,10 @@ u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
        return 0;
 }
 
-u32 fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
+int fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_TX)
                return -EPERM;
@@ -176,10 +176,10 @@ u32 fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
        return 0;
 }
 
-u32 fm_tx_set_af(struct fmdev *fmdev, u32 af)
+int fm_tx_set_af(struct fmdev *fmdev, u32 af)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_TX)
                return -EPERM;
@@ -196,10 +196,10 @@ u32 fm_tx_set_af(struct fmdev *fmdev, u32 af)
        return 0;
 }
 
-u32 fm_tx_set_region(struct fmdev *fmdev, u8 region)
+int fm_tx_set_region(struct fmdev *fmdev, u8 region)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) {
                fmerr("Invalid band\n");
@@ -216,10 +216,10 @@ u32 fm_tx_set_region(struct fmdev *fmdev, u8 region)
        return 0;
 }
 
-u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
 {
        u16 payload;
-       u32 ret;
+       int ret;
 
        fmdbg("tx: mute mode %d\n", mute_mode_toset);
 
@@ -233,11 +233,11 @@ u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
 }
 
 /* Set TX Audio I/O */
-static u32 set_audio_io(struct fmdev *fmdev)
+static int set_audio_io(struct fmdev *fmdev)
 {
        struct fmtx_data *tx = &fmdev->tx_data;
        u16 payload;
-       u32 ret;
+       int ret;
 
        /* Set Audio I/O Enable */
        payload = tx->audio_io;
@@ -251,12 +251,12 @@ static u32 set_audio_io(struct fmdev *fmdev)
 }
 
 /* Start TX Transmission */
-static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
+static int enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
 {
        struct fmtx_data *tx = &fmdev->tx_data;
        unsigned long timeleft;
        u16 payload;
-       u32 ret;
+       int ret;
 
        /* Enable POWER_ENB interrupts */
        payload = FM_POW_ENB_EVENT;
@@ -289,11 +289,11 @@ static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
 }
 
 /* Set TX power level */
-u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
+int fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
 {
        u16 payload;
        struct fmtx_data *tx = &fmdev->tx_data;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_TX)
                return -EPERM;
@@ -328,11 +328,11 @@ u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
  * Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us)
  * Convert V4L2 specified filter values to chip specific filter values.
  */
-u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
+int fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
 {
        struct fmtx_data *tx = &fmdev->tx_data;
        u16 payload;
-       u32 ret;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_TX)
                return -EPERM;
@@ -360,10 +360,11 @@ u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
 }
 
 /* Get the TX tuning capacitor value.*/
-u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev)
+int fm_tx_get_tune_cap_val(struct fmdev *fmdev)
 {
        u16 curr_val;
-       u32 ret, resp_len;
+       u32 resp_len;
+       int ret;
 
        if (fmdev->curr_fmmode != FM_MODE_TX)
                return -EPERM;
@@ -379,11 +380,11 @@ u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev)
 }
 
 /* Set TX Frequency */
-u32 fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+int fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
 {
        struct fmtx_data *tx = &fmdev->tx_data;
        u16 payload, chanl_index;
-       u32 ret;
+       int ret;
 
        if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) {
                enable_xmit(fmdev, 0);
index e393a2bdd49e63fd9ed5d8bb6cbf065d9c134baa..11ae2e4c2d033e586bfcda18db1754aa9462fe8b 100644 (file)
 #ifndef _FMDRV_TX_H
 #define _FMDRV_TX_H
 
-u32 fm_tx_set_freq(struct fmdev *, u32);
-u32 fm_tx_set_pwr_lvl(struct fmdev *, u8);
-u32 fm_tx_set_region(struct fmdev *, u8);
-u32 fm_tx_set_mute_mode(struct fmdev *, u8);
-u32 fm_tx_set_stereo_mono(struct fmdev *, u16);
-u32 fm_tx_set_rds_mode(struct fmdev *, u8);
-u32 fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
-u32 fm_tx_set_af(struct fmdev *, u32);
-u32 fm_tx_set_preemph_filter(struct fmdev *, u32);
-u32 fm_tx_get_tune_cap_val(struct fmdev *);
+int fm_tx_set_freq(struct fmdev *, u32);
+int fm_tx_set_pwr_lvl(struct fmdev *, u8);
+int fm_tx_set_region(struct fmdev *, u8);
+int fm_tx_set_mute_mode(struct fmdev *, u8);
+int fm_tx_set_stereo_mono(struct fmdev *, u16);
+int fm_tx_set_rds_mode(struct fmdev *, u8);
+int fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
+int fm_tx_set_af(struct fmdev *, u32);
+int fm_tx_set_preemph_filter(struct fmdev *, u32);
+int fm_tx_get_tune_cap_val(struct fmdev *);
 
 #endif
 
index 4f5c43d2566c887444a91329b64a3960229e5278..077d369a017318e40849466c92bea074c94b46c1 100644 (file)
@@ -84,6 +84,7 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
        struct fmdev *fmdev;
 
        ret = copy_from_user(&rds, buf, sizeof(rds));
+       rds.text[sizeof(rds.text) - 1] = '\0';
        fmdbg("(%d)type: %d, text %s, af %d\n",
                   ret, rds.text_type, rds.text, rds.af_freq);
        if (ret)
index aeb7f43dfb652790b053192bceeca1f9fdf31758..4df4affeea5f1537d72a8383c970f472b34635b1 100644 (file)
@@ -87,6 +87,16 @@ config IR_RC5_SZ_DECODER
           uses an IR protocol that is almost standard RC-5, but not quite,
           as it uses an additional bit).
 
+config IR_SANYO_DECODER
+       tristate "Enable IR raw decoder for the Sanyo protocol"
+       depends on RC_CORE
+       default y
+
+       ---help---
+          Enable this option if you have an infrared remote control which
+          uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes),
+          and you need software decoding support.
+
 config IR_MCE_KBD_DECODER
        tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol"
        depends on RC_CORE
index 2156e786b5571194bbe36b69c4ac1e610cbfc75c..fb3dee2dd84584788c14af2ef0aab4816a0c88bb 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
 obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
+obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
 obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
index 17f8db00435ac70269823ae3f029968cebbbd72a..3c9431a9f62d282d37238ab6089cd63ca73ad77b 100644 (file)
@@ -194,8 +194,8 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
                return 0;
        }
 
-       IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
-                  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+       IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",
+                  data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
        data->state = STATE_INACTIVE;
        return -EINVAL;
 }
index 2e5cd3100b64476da15ef33508cbd39dd42ded50..95e630998aaf42d2e2441514f62713038ab41fdc 100644 (file)
@@ -357,6 +357,7 @@ static void init_decoders(struct work_struct *work)
        load_rc6_decode();
        load_jvc_decode();
        load_sony_decode();
+       load_sanyo_decode();
        load_mce_kbd_decode();
        load_lirc_codec();
 
index 140fb67e2f89d9be9ce79a1b475a2fb24a900140..4cfdd7fa4bbd56b7d04f130b78020f8977ebaec6 100644 (file)
 /*
  * This decoder currently supports:
  * RC6-0-16    (standard toggle bit in header)
+ * RC6-6A-20   (no toggle bit)
  * RC6-6A-24   (no toggle bit)
  * RC6-6A-32   (MCE version with toggle bit in body)
  */
 
-#define RC6_UNIT               444444  /* us */
+#define RC6_UNIT               444444  /* nanosecs */
 #define RC6_HEADER_NBITS       4       /* not including toggle bit */
 #define RC6_0_NBITS            16
-#define RC6_6A_SMALL_NBITS     24
-#define RC6_6A_LARGE_NBITS     32
+#define RC6_6A_32_NBITS                32
+#define RC6_6A_NBITS           128     /* Variable 8..128 */
 #define RC6_PREFIX_PULSE       (6 * RC6_UNIT)
 #define RC6_PREFIX_SPACE       (2 * RC6_UNIT)
 #define RC6_BIT_START          (1 * RC6_UNIT)
 #define RC6_BIT_END            (1 * RC6_UNIT)
 #define RC6_TOGGLE_START       (2 * RC6_UNIT)
 #define RC6_TOGGLE_END         (2 * RC6_UNIT)
+#define RC6_SUFFIX_SPACE       (6 * RC6_UNIT)
 #define RC6_MODE_MASK          0x07    /* for the header bits */
 #define RC6_STARTBIT_MASK      0x08    /* for the header bits */
 #define RC6_6A_MCE_TOGGLE_MASK 0x8000  /* for the body bits */
+#define RC6_6A_LCC_MASK                0xffff0000 /* RC6-6A-32 long customer code mask */
+#define RC6_6A_MCE_CC          0x800f0000 /* MCE customer code */
+#ifndef CHAR_BIT
+#define CHAR_BIT 8     /* Normally in <limits.h> */
+#endif
 
 enum rc6_mode {
        RC6_MODE_0,
@@ -125,6 +132,7 @@ again:
                        break;
 
                data->state = STATE_HEADER_BIT_START;
+               data->header = 0;
                return 0;
 
        case STATE_HEADER_BIT_START:
@@ -171,20 +179,14 @@ again:
                data->state = STATE_BODY_BIT_START;
                decrease_duration(&ev, RC6_TOGGLE_END);
                data->count = 0;
+               data->body = 0;
 
                switch (rc6_mode(data)) {
                case RC6_MODE_0:
                        data->wanted_bits = RC6_0_NBITS;
                        break;
                case RC6_MODE_6A:
-                       /* This might look weird, but we basically
-                          check the value of the first body bit to
-                          determine the number of bits in mode 6A */
-                       if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
-                           geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
-                               data->wanted_bits = RC6_6A_LARGE_NBITS;
-                       else
-                               data->wanted_bits = RC6_6A_SMALL_NBITS;
+                       data->wanted_bits = RC6_6A_NBITS;
                        break;
                default:
                        IR_dprintk(1, "RC6 unknown mode\n");
@@ -193,15 +195,21 @@ again:
                goto again;
 
        case STATE_BODY_BIT_START:
-               if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
-                       break;
-
-               data->body <<= 1;
-               if (ev.pulse)
-                       data->body |= 1;
-               data->count++;
-               data->state = STATE_BODY_BIT_END;
-               return 0;
+               if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
+                       /* Discard LSB's that won't fit in data->body */
+                       if (data->count++ < CHAR_BIT * sizeof data->body) {
+                               data->body <<= 1;
+                               if (ev.pulse)
+                                       data->body |= 1;
+                       }
+                       data->state = STATE_BODY_BIT_END;
+                       return 0;
+               } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
+                               geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
+                       data->state = STATE_FINISHED;
+                       goto again;
+               }
+               break;
 
        case STATE_BODY_BIT_END:
                if (!is_transition(&ev, &dev->raw->prev_ev))
@@ -221,20 +229,27 @@ again:
 
                switch (rc6_mode(data)) {
                case RC6_MODE_0:
-                       scancode = data->body & 0xffff;
+                       scancode = data->body;
                        toggle = data->toggle;
                        IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
                                   scancode, toggle);
                        break;
                case RC6_MODE_6A:
-                       if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
-                               toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
-                               scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
+                       if (data->count > CHAR_BIT * sizeof data->body) {
+                               IR_dprintk(1, "RC6 too many (%u) data bits\n",
+                                       data->count);
+                               goto out;
+                       }
+
+                       scancode = data->body;
+                       if (data->count == RC6_6A_32_NBITS &&
+                                       (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+                               /* MCE RC */
+                               toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
+                               scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
                        } else {
                                toggle = 0;
-                               scancode = data->body & 0xffffff;
                        }
-
                        IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
                                   scancode, toggle);
                        break;
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
new file mode 100644 (file)
index 0000000..d38fbdd
--- /dev/null
@@ -0,0 +1,205 @@
+/* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol
+ *
+ * Copyright (C) 2011 by Mauro Carvalho Chehab <mchehab@redhat.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 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.
+ *
+ * This protocol uses the NEC protocol timings. However, data is formatted as:
+ *     13 bits Custom Code
+ *     13 bits NOT(Custom Code)
+ *     8 bits Key data
+ *     8 bits NOT(Key data)
+ *
+ * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
+ * Information for this protocol is available at the Sanyo LC7461 datasheet.
+ */
+
+#include <linux/module.h>
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define SANYO_NBITS            (13+13+8+8)
+#define SANYO_UNIT             562500  /* ns */
+#define SANYO_HEADER_PULSE     (16  * SANYO_UNIT)
+#define SANYO_HEADER_SPACE     (8   * SANYO_UNIT)
+#define SANYO_BIT_PULSE                (1   * SANYO_UNIT)
+#define SANYO_BIT_0_SPACE      (1   * SANYO_UNIT)
+#define SANYO_BIT_1_SPACE      (3   * SANYO_UNIT)
+#define SANYO_REPEAT_SPACE     (150 * SANYO_UNIT)
+#define        SANYO_TRAILER_PULSE     (1   * SANYO_UNIT)
+#define        SANYO_TRAILER_SPACE     (10  * SANYO_UNIT)      /* in fact, 42 */
+
+enum sanyo_state {
+       STATE_INACTIVE,
+       STATE_HEADER_SPACE,
+       STATE_BIT_PULSE,
+       STATE_BIT_SPACE,
+       STATE_TRAILER_PULSE,
+       STATE_TRAILER_SPACE,
+};
+
+/**
+ * ir_sanyo_decode() - Decode one SANYO pulse or space
+ * @dev:       the struct rc_dev descriptor of the device
+ * @duration:  the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+       struct sanyo_dec *data = &dev->raw->sanyo;
+       u32 scancode;
+       u8 address, not_address, command, not_command;
+
+       if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+               return 0;
+
+       if (!is_timing_event(ev)) {
+               if (ev.reset) {
+                       IR_dprintk(1, "SANYO event reset received. reset to state 0\n");
+                       data->state = STATE_INACTIVE;
+               }
+               return 0;
+       }
+
+       IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n",
+                  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+       switch (data->state) {
+
+       case STATE_INACTIVE:
+               if (!ev.pulse)
+                       break;
+
+               if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) {
+                       data->count = 0;
+                       data->state = STATE_HEADER_SPACE;
+                       return 0;
+               }
+               break;
+
+
+       case STATE_HEADER_SPACE:
+               if (ev.pulse)
+                       break;
+
+               if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) {
+                       data->state = STATE_BIT_PULSE;
+                       return 0;
+               }
+
+               break;
+
+       case STATE_BIT_PULSE:
+               if (!ev.pulse)
+                       break;
+
+               if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2))
+                       break;
+
+               data->state = STATE_BIT_SPACE;
+               return 0;
+
+       case STATE_BIT_SPACE:
+               if (ev.pulse)
+                       break;
+
+               if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) {
+                       if (!dev->keypressed) {
+                               IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n");
+                       } else {
+                               rc_repeat(dev);
+                               IR_dprintk(1, "SANYO repeat last key\n");
+                               data->state = STATE_INACTIVE;
+                       }
+                       return 0;
+               }
+
+               data->bits <<= 1;
+               if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2))
+                       data->bits |= 1;
+               else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2))
+                       break;
+               data->count++;
+
+               if (data->count == SANYO_NBITS)
+                       data->state = STATE_TRAILER_PULSE;
+               else
+                       data->state = STATE_BIT_PULSE;
+
+               return 0;
+
+       case STATE_TRAILER_PULSE:
+               if (!ev.pulse)
+                       break;
+
+               if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2))
+                       break;
+
+               data->state = STATE_TRAILER_SPACE;
+               return 0;
+
+       case STATE_TRAILER_SPACE:
+               if (ev.pulse)
+                       break;
+
+               if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2))
+                       break;
+
+               address     = bitrev16((data->bits >> 29) & 0x1fff) >> 3;
+               not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3;
+               command     = bitrev8((data->bits >>  8) & 0xff);
+               not_command = bitrev8((data->bits >>  0) & 0xff);
+
+               if ((command ^ not_command) != 0xff) {
+                       IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n",
+                                  data->bits);
+                       data->state = STATE_INACTIVE;
+                       return 0;
+               }
+
+               scancode = address << 8 | command;
+               IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
+               rc_keydown(dev, scancode, 0);
+               data->state = STATE_INACTIVE;
+               return 0;
+       }
+
+       IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n",
+                  data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+       data->state = STATE_INACTIVE;
+       return -EINVAL;
+}
+
+static struct ir_raw_handler sanyo_handler = {
+       .protocols      = RC_TYPE_SANYO,
+       .decode         = ir_sanyo_decode,
+};
+
+static int __init ir_sanyo_decode_init(void)
+{
+       ir_raw_handler_register(&sanyo_handler);
+
+       printk(KERN_INFO "IR SANYO protocol handler initialized\n");
+       return 0;
+}
+
+static void __exit ir_sanyo_decode_exit(void)
+{
+       ir_raw_handler_unregister(&sanyo_handler);
+}
+
+module_init(ir_sanyo_decode_init);
+module_exit(ir_sanyo_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("SANYO IR protocol decoder");
index e51c6163378b5e0bece020e4a615da5b0095640c..929bbbc163931ca9e9883b471d293754d0f75e33 100644 (file)
@@ -182,6 +182,57 @@ static struct rc_map_table rc5_hauppauge_new[] = {
        { 0x1d3d, KEY_POWER },
        { 0x1d3f, KEY_HOME },
 
+       /*
+        * Keycodes for PT# R-005 remote bundled with Haupauge HVR-930C
+        * Keycodes start with address = 0x1c
+        */
+       { 0x1c3b, KEY_GOTO },
+       { 0x1c3d, KEY_POWER },
+
+       { 0x1c14, KEY_UP },
+       { 0x1c15, KEY_DOWN },
+       { 0x1c16, KEY_LEFT },
+       { 0x1c17, KEY_RIGHT },
+       { 0x1c25, KEY_OK },
+
+       { 0x1c00, KEY_0 },
+       { 0x1c01, KEY_1 },
+       { 0x1c02, KEY_2 },
+       { 0x1c03, KEY_3 },
+       { 0x1c04, KEY_4 },
+       { 0x1c05, KEY_5 },
+       { 0x1c06, KEY_6 },
+       { 0x1c07, KEY_7 },
+       { 0x1c08, KEY_8 },
+       { 0x1c09, KEY_9 },
+
+       { 0x1c1f, KEY_EXIT },   /* BACK */
+       { 0x1c0d, KEY_MENU },
+       { 0x1c1c, KEY_TV },
+
+       { 0x1c10, KEY_VOLUMEUP },
+       { 0x1c11, KEY_VOLUMEDOWN },
+
+       { 0x1c20, KEY_CHANNELUP },
+       { 0x1c21, KEY_CHANNELDOWN },
+
+       { 0x1c0f, KEY_MUTE },
+       { 0x1c12, KEY_PREVIOUS }, /* Prev */
+
+       { 0x1c36, KEY_STOP },
+       { 0x1c37, KEY_RECORD },
+
+       { 0x1c24, KEY_LAST },           /* <|             */
+       { 0x1c1e, KEY_NEXT },           /* >|             */
+
+       { 0x1c0a, KEY_TEXT },
+       { 0x1c0e, KEY_SUBTITLE },       /* CC */
+
+       { 0x1c32, KEY_REWIND },
+       { 0x1c30, KEY_PAUSE },
+       { 0x1c35, KEY_PLAY },
+       { 0x1c34, KEY_FASTFORWARD },
+
        /*
         * Keycodes for the old Black Remote Controller
         * This one also uses RC-5 protocol
index 3bd1de1f585c198d54c73ae16b018c6471ce8e35..23ee05e539498ebd6d87e7fc515f2f75fc109ecf 100644 (file)
@@ -1,4 +1,4 @@
-/* videomate-m1f.h - Keytable for videomate_m1f Remote Controller
+/* videomate-k100.h - Keytable for videomate_k100 Remote Controller
  *
  * keymap imported from ir-keymaps.c
  *
@@ -13,7 +13,7 @@
 #include <media/rc-map.h>
 #include <linux/module.h>
 
-static struct rc_map_table videomate_m1f[] = {
+static struct rc_map_table videomate_k100[] = {
        { 0x01, KEY_POWER },
        { 0x31, KEY_TUNER },
        { 0x33, KEY_VIDEO },
@@ -67,27 +67,27 @@ static struct rc_map_table videomate_m1f[] = {
        { 0x18, KEY_TEXT },
 };
 
-static struct rc_map_list videomate_m1f_map = {
+static struct rc_map_list videomate_k100_map = {
        .map = {
-               .scan    = videomate_m1f,
-               .size    = ARRAY_SIZE(videomate_m1f),
+               .scan    = videomate_k100,
+               .size    = ARRAY_SIZE(videomate_k100),
                .rc_type = RC_TYPE_UNKNOWN,     /* Legacy IR type */
-               .name    = RC_MAP_VIDEOMATE_M1F,
+               .name    = RC_MAP_VIDEOMATE_K100,
        }
 };
 
-static int __init init_rc_map_videomate_m1f(void)
+static int __init init_rc_map_videomate_k100(void)
 {
-       return rc_map_register(&videomate_m1f_map);
+       return rc_map_register(&videomate_k100_map);
 }
 
-static void __exit exit_rc_map_videomate_m1f(void)
+static void __exit exit_rc_map_videomate_k100(void)
 {
-       rc_map_unregister(&videomate_m1f_map);
+       rc_map_unregister(&videomate_k100_map);
 }
 
-module_init(init_rc_map_videomate_m1f)
-module_exit(exit_rc_map_videomate_m1f)
+module_init(init_rc_map_videomate_k100)
+module_exit(exit_rc_map_videomate_k100)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pavel Osnova <pvosnova@gmail.com>");
index c6ca870e8b7eb1e2a112b8da1670cd896ed12e1d..b72f8580e3170ba14b629cab0e0ae88d9d83095f 100644 (file)
@@ -84,6 +84,11 @@ struct ir_raw_event_ctrl {
                unsigned count;
                unsigned wanted_bits;
        } rc5_sz;
+       struct sanyo_dec {
+               int state;
+               unsigned count;
+               u64 bits;
+       } sanyo;
        struct mce_kbd_dec {
                struct input_dev *idev;
                struct timer_list rx_timeout;
@@ -193,6 +198,13 @@ static inline void load_jvc_decode(void) { }
 static inline void load_sony_decode(void) { }
 #endif
 
+/* from ir-sanyo-decoder.c */
+#ifdef CONFIG_IR_SANYO_DECODER_MODULE
+#define load_sanyo_decode()    request_module("ir-sanyo-decoder")
+#else
+static inline void load_sanyo_decode(void) { }
+#endif
+
 /* from ir-mce_kbd-decoder.c */
 #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
 #define load_mce_kbd_decode()  request_module("ir-mce_kbd-decoder")
index f5db8b949bc3907f0367d7771724190529f81e29..f6a930b70c69586f67d3ac64ec0227c1afa1e623 100644 (file)
@@ -736,6 +736,7 @@ static struct {
        { RC_TYPE_JVC,          "jvc"           },
        { RC_TYPE_SONY,         "sony"          },
        { RC_TYPE_RC5_SZ,       "rc-5-sz"       },
+       { RC_TYPE_SANYO,        "sanyo"         },
        { RC_TYPE_MCE_KBD,      "mce_kbd"       },
        { RC_TYPE_LIRC,         "lirc"          },
        { RC_TYPE_OTHER,        "other"         },
index 07322fb75eff5a42921584dbac8bc0dc8408ae1f..ad95c67a4dbafacbbd227f81cd703372dd9dc3cc 100644 (file)
@@ -286,12 +286,6 @@ static void redrat3_issue_async(struct redrat3_dev *rr3)
 
        rr3_ftr(rr3->dev, "Entering %s\n", __func__);
 
-       if (!rr3->det_enabled) {
-               dev_warn(rr3->dev, "not issuing async read, "
-                        "detector not enabled\n");
-               return;
-       }
-
        memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize);
        res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
        if (res)
@@ -827,6 +821,7 @@ out:
 static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
 {
        struct redrat3_dev *rr3;
+       int ret;
 
        if (!urb)
                return;
@@ -840,15 +835,13 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
 
        rr3_ftr(rr3->dev, "Entering %s\n", __func__);
 
-       if (!rr3->det_enabled) {
-               rr3_dbg(rr3->dev, "received a read callback but detector "
-                       "disabled - ignoring\n");
-               return;
-       }
-
        switch (urb->status) {
        case 0:
-               redrat3_get_ir_data(rr3, urb->actual_length);
+               ret = redrat3_get_ir_data(rr3, urb->actual_length);
+               if (!ret) {
+                       /* no error, prepare to read more */
+                       redrat3_issue_async(rr3);
+               }
                break;
 
        case -ECONNRESET:
@@ -865,11 +858,6 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
                rr3->pkttype = 0;
                break;
        }
-
-       if (!rr3->transmitting)
-               redrat3_issue_async(rr3);
-       else
-               rr3_dbg(rr3->dev, "IR transmit in progress\n");
 }
 
 static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
@@ -896,21 +884,24 @@ static u16 mod_freq_to_val(unsigned int mod_freq)
        return (u16)(65536 - (mult / mod_freq));
 }
 
-static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
 {
-       struct redrat3_dev *rr3 = dev->priv;
+       struct redrat3_dev *rr3 = rcdev->priv;
+       struct device *dev = rr3->dev;
 
+       rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
        rr3->carrier = carrier;
 
        return carrier;
 }
 
-static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
+                               unsigned count)
 {
        struct redrat3_dev *rr3 = rcdev->priv;
        struct device *dev = rr3->dev;
        struct redrat3_signal_header header;
-       int i, j, count, ret, ret_len, offset;
+       int i, j, ret, ret_len, offset;
        int lencheck, cur_sample_len, pipe;
        char *buffer = NULL, *sigdata = NULL;
        int *sample_lens = NULL;
@@ -928,20 +919,13 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
                return -EAGAIN;
        }
 
-       count = n / sizeof(int);
        if (count > (RR3_DRIVER_MAXLENS * 2))
                return -EINVAL;
 
+       /* rr3 will disable rc detector on transmit */
+       rr3->det_enabled = false;
        rr3->transmitting = true;
 
-       redrat3_disable_detector(rr3);
-
-       if (rr3->det_enabled) {
-               dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__);
-               ret = -EIO;
-               goto out;
-       }
-
        sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
        if (!sample_lens) {
                ret = -ENOMEM;
@@ -1055,7 +1039,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
        if (ret < 0)
                dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
        else
-               ret = n;
+               ret = count;
 
 out:
        kfree(sample_lens);
@@ -1063,8 +1047,8 @@ out:
        kfree(sigdata);
 
        rr3->transmitting = false;
-
-       redrat3_enable_detector(rr3);
+       /* rr3 re-enables rc detector because it was enabled before */
+       rr3->det_enabled = true;
 
        return ret;
 }
index b303a3f8a9f8ac776f83511740e52d91e36095e4..9adada0d7447ba60758a7852c2f1b05829e8411e 100644 (file)
@@ -533,6 +533,13 @@ config VIDEO_ADP1653
          This is a driver for the ADP1653 flash controller. It is used for
          example in Nokia N900.
 
+config VIDEO_AS3645A
+       tristate "AS3645A flash driver support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       ---help---
+         This is a driver for the AS3645A and LM3555 flash controllers. It has
+         build in control for flash, torch and indicator LEDs.
+
 comment "Video improvement chips"
 
 config VIDEO_UPD64031A
@@ -580,25 +587,6 @@ config VIDEO_M52790
 
 endmenu # encoder / decoder chips
 
-config VIDEO_SH_VOU
-       tristate "SuperH VOU video output driver"
-       depends on VIDEO_DEV && ARCH_SHMOBILE
-       select VIDEOBUF_DMA_CONTIG
-       help
-         Support for the Video Output Unit (VOU) on SuperH SoCs.
-
-config VIDEO_VIU
-       tristate "Freescale VIU Video Driver"
-       depends on VIDEO_V4L2 && PPC_MPC512x
-       select VIDEOBUF_DMA_CONTIG
-       default y
-       ---help---
-         Support for Freescale VIU video driver. This device captures
-         video data, or overlays video on DIU frame buffer.
-
-         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
-         In doubt, say N.
-
 config VIDEO_VIVI
        tristate "Virtual Video Driver"
        depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
@@ -613,66 +601,130 @@ config VIDEO_VIVI
          Say Y here if you want to test video apps or debug V4L devices.
          In doubt, say N.
 
-source "drivers/media/video/davinci/Kconfig"
+#
+# USB Multimedia device configuration
+#
 
-source "drivers/media/video/omap/Kconfig"
+menuconfig V4L_USB_DRIVERS
+       bool "V4L USB devices"
+       depends on USB
+       default y
 
-source "drivers/media/video/bt8xx/Kconfig"
+if V4L_USB_DRIVERS
 
-config VIDEO_PMS
-       tristate "Mediavision Pro Movie Studio Video For Linux"
-       depends on ISA && VIDEO_V4L2
-       help
-         Say Y if you have such a thing.
+source "drivers/media/video/uvc/Kconfig"
+
+source "drivers/media/video/gspca/Kconfig"
+
+source "drivers/media/video/pvrusb2/Kconfig"
+
+source "drivers/media/video/hdpvr/Kconfig"
+
+source "drivers/media/video/em28xx/Kconfig"
+
+source "drivers/media/video/tlg2300/Kconfig"
+
+source "drivers/media/video/cx231xx/Kconfig"
+
+source "drivers/media/video/tm6000/Kconfig"
+
+source "drivers/media/video/usbvision/Kconfig"
+
+source "drivers/media/video/et61x251/Kconfig"
+
+source "drivers/media/video/sn9c102/Kconfig"
+
+source "drivers/media/video/pwc/Kconfig"
+
+source "drivers/media/video/cpia2/Kconfig"
+
+config USB_ZR364XX
+       tristate "USB ZR364XX Camera support"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_GEN
+       select VIDEOBUF_VMALLOC
+       ---help---
+         Say Y here if you want to connect this type of camera to your
+         computer's USB port.
+         See <file:Documentation/video4linux/zr364xx.txt> for more info
+         and list of supported cameras.
 
          To compile this driver as a module, choose M here: the
-         module will be called pms.
+         module will be called zr364xx.
 
-config VIDEO_BWQCAM
-       tristate "Quickcam BW Video For Linux"
-       depends on PARPORT && VIDEO_V4L2
-       help
-         Say Y have if you the black and white version of the QuickCam
-         camera. See the next option for the color version.
+config USB_STKWEBCAM
+       tristate "USB Syntek DC1125 Camera support"
+       depends on VIDEO_V4L2 && EXPERIMENTAL
+       ---help---
+         Say Y here if you want to use this type of camera.
+         Supported devices are typically found in some Asus laptops,
+         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
+         may be supported by the stk11xx driver, from which this is
+         derived, see <http://sourceforge.net/projects/syntekdriver/>
 
          To compile this driver as a module, choose M here: the
-         module will be called bw-qcam.
+         module will be called stkwebcam.
 
-config VIDEO_CQCAM
-       tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
+config USB_S2255
+       tristate "USB Sensoray 2255 video capture device"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_VMALLOC
+       default n
        help
-         This is the video4linux driver for the colour version of the
-         Connectix QuickCam.  If you have one of these cameras, say Y here,
-         otherwise say N.  This driver does not work with the original
-         monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
-         as a module (c-qcam).
-         Read <file:Documentation/video4linux/CQcam.txt> for more information.
+         Say Y here if you want support for the Sensoray 2255 USB device.
+         This driver can be compiled as a module, called s2255drv.
 
-config VIDEO_W9966
-       tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
-       depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
-       help
-         Video4linux driver for Winbond's w9966 based Webcams.
-         Currently tested with the LifeView FlyCam Supra.
-         If you have one of these cameras, say Y here
-         otherwise say N.
-         This driver is also available as a module (w9966).
+endif # V4L_USB_DRIVERS
 
-         Check out <file:Documentation/video4linux/w9966.txt> for more
-         information.
+#
+# PCI drivers configuration
+#
 
-source "drivers/media/video/cpia2/Kconfig"
+menuconfig V4L_PCI_DRIVERS
+       bool "V4L PCI(e) devices"
+       depends on PCI
+       default y
+       ---help---
+         Say Y here to enable support for these PCI(e) drivers.
 
-config VIDEO_VINO
-       tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
-       depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
-       select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Say Y here to build in support for the Vino video input system found
-         on SGI Indy machines.
+if V4L_PCI_DRIVERS
 
-source "drivers/media/video/zoran/Kconfig"
+source "drivers/media/video/au0828/Kconfig"
+
+source "drivers/media/video/bt8xx/Kconfig"
+
+source "drivers/media/video/cx18/Kconfig"
+
+source "drivers/media/video/cx23885/Kconfig"
+
+source "drivers/media/video/cx25821/Kconfig"
+
+source "drivers/media/video/cx88/Kconfig"
+
+config VIDEO_HEXIUM_GEMINI
+       tristate "Hexium Gemini frame grabber"
+       depends on PCI && VIDEO_V4L2 && I2C
+       select VIDEO_SAA7146_VV
+       ---help---
+         This is a video4linux driver for the Hexium Gemini frame
+         grabber card by Hexium. Please note that the Gemini Dual
+         card is *not* fully supported.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hexium_gemini.
+
+config VIDEO_HEXIUM_ORION
+       tristate "Hexium HV-PCI6 and Orion frame grabber"
+       depends on PCI && VIDEO_V4L2 && I2C
+       select VIDEO_SAA7146_VV
+       ---help---
+         This is a video4linux driver for the Hexium HV-PCI6 and
+         Orion frame grabber cards by Hexium.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hexium_orion.
+
+source "drivers/media/video/ivtv/Kconfig"
 
 config VIDEO_MEYE
        tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
@@ -688,8 +740,6 @@ config VIDEO_MEYE
          To compile this driver as a module, choose M here: the
          module will be called meye.
 
-source "drivers/media/video/saa7134/Kconfig"
-
 config VIDEO_MXB
        tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
        depends on PCI && VIDEO_V4L2 && I2C
@@ -706,28 +756,119 @@ config VIDEO_MXB
          To compile this driver as a module, choose M here: the
          module will be called mxb.
 
-config VIDEO_HEXIUM_ORION
-       tristate "Hexium HV-PCI6 and Orion frame grabber"
-       depends on PCI && VIDEO_V4L2 && I2C
-       select VIDEO_SAA7146_VV
+source "drivers/media/video/saa7134/Kconfig"
+
+source "drivers/media/video/saa7164/Kconfig"
+
+source "drivers/media/video/zoran/Kconfig"
+
+endif # V4L_PCI_DRIVERS
+
+#
+# ISA & parallel port drivers configuration
+#
+
+menuconfig V4L_ISA_PARPORT_DRIVERS
+       bool "V4L ISA and parallel port devices"
+       depends on ISA || PARPORT
+       default n
        ---help---
-         This is a video4linux driver for the Hexium HV-PCI6 and
-         Orion frame grabber cards by Hexium.
+         Say Y here to enable support for these ISA and parallel port drivers.
+
+if V4L_ISA_PARPORT_DRIVERS
+
+config VIDEO_BWQCAM
+       tristate "Quickcam BW Video For Linux"
+       depends on PARPORT && VIDEO_V4L2
+       help
+         Say Y have if you the black and white version of the QuickCam
+         camera. See the next option for the color version.
 
          To compile this driver as a module, choose M here: the
-         module will be called hexium_orion.
+         module will be called bw-qcam.
 
-config VIDEO_HEXIUM_GEMINI
-       tristate "Hexium Gemini frame grabber"
-       depends on PCI && VIDEO_V4L2 && I2C
-       select VIDEO_SAA7146_VV
-       ---help---
-         This is a video4linux driver for the Hexium Gemini frame
-         grabber card by Hexium. Please note that the Gemini Dual
-         card is *not* fully supported.
+config VIDEO_CQCAM
+       tristate "QuickCam Colour Video For Linux"
+       depends on PARPORT && VIDEO_V4L2
+       help
+         This is the video4linux driver for the colour version of the
+         Connectix QuickCam.  If you have one of these cameras, say Y here,
+         otherwise say N.  This driver does not work with the original
+         monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
+         as a module (c-qcam).
+         Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+config VIDEO_PMS
+       tristate "Mediavision Pro Movie Studio Video For Linux"
+       depends on ISA && VIDEO_V4L2
+       help
+         Say Y if you have the ISA Mediavision Pro Movie Studio
+         capture card.
 
          To compile this driver as a module, choose M here: the
-         module will be called hexium_gemini.
+         module will be called pms.
+
+config VIDEO_W9966
+       tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
+       depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
+       help
+         Video4linux driver for Winbond's w9966 based Webcams.
+         Currently tested with the LifeView FlyCam Supra.
+         If you have one of these cameras, say Y here
+         otherwise say N.
+         This driver is also available as a module (w9966).
+
+         Check out <file:Documentation/video4linux/w9966.txt> for more
+         information.
+
+endif # V4L_ISA_PARPORT_DRIVERS
+
+menuconfig V4L_PLATFORM_DRIVERS
+       bool "V4L platform devices"
+       default n
+       ---help---
+         Say Y here to enable support for platform-specific V4L drivers.
+
+if V4L_PLATFORM_DRIVERS
+
+source "drivers/media/video/marvell-ccic/Kconfig"
+
+config VIDEO_VIA_CAMERA
+       tristate "VIAFB camera controller support"
+       depends on FB_VIA
+       select VIDEOBUF_DMA_SG
+       select VIDEO_OV7670
+       help
+          Driver support for the integrated camera controller in VIA
+          Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
+          with ov7670 sensors.
+
+#
+# Platform multimedia device configuration
+#
+
+source "drivers/media/video/davinci/Kconfig"
+
+source "drivers/media/video/omap/Kconfig"
+
+config VIDEO_SH_VOU
+       tristate "SuperH VOU video output driver"
+       depends on VIDEO_DEV && ARCH_SHMOBILE
+       select VIDEOBUF_DMA_CONTIG
+       help
+         Support for the Video Output Unit (VOU) on SuperH SoCs.
+
+config VIDEO_VIU
+       tristate "Freescale VIU Video Driver"
+       depends on VIDEO_V4L2 && PPC_MPC512x
+       select VIDEOBUF_DMA_CONTIG
+       default y
+       ---help---
+         Support for Freescale VIU video driver. This device captures
+         video data, or overlays video on DIU frame buffer.
+
+         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
+         In doubt, say N.
 
 config VIDEO_TIMBERDALE
        tristate "Support for timberdale Video In/LogiWIN"
@@ -739,21 +880,13 @@ config VIDEO_TIMBERDALE
        ---help---
          Add support for the Video In peripherial of the timberdale FPGA.
 
-source "drivers/media/video/cx88/Kconfig"
-
-source "drivers/media/video/cx23885/Kconfig"
-
-source "drivers/media/video/cx25821/Kconfig"
-
-source "drivers/media/video/au0828/Kconfig"
-
-source "drivers/media/video/ivtv/Kconfig"
-
-source "drivers/media/video/cx18/Kconfig"
-
-source "drivers/media/video/saa7164/Kconfig"
-
-source "drivers/media/video/marvell-ccic/Kconfig"
+config VIDEO_VINO
+       tristate "SGI Vino Video For Linux"
+       depends on I2C && SGI_IP22 && VIDEO_V4L2
+       select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Say Y here to build in support for the Vino video input system found
+         on SGI Indy machines.
 
 config VIDEO_M32R_AR
        tristate "AR devices"
@@ -774,16 +907,6 @@ config VIDEO_M32R_AR_M64278
          To compile this driver as a module, choose M here: the
          module will be called arv.
 
-config VIDEO_VIA_CAMERA
-       tristate "VIAFB camera controller support"
-       depends on FB_VIA
-       select VIDEOBUF_DMA_SG
-       select VIDEO_OV7670
-       help
-          Driver support for the integrated camera controller in VIA
-          Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
-          with ov7670 sensors.
-
 config VIDEO_OMAP3
        tristate "OMAP 3 Camera support (EXPERIMENTAL)"
        depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
@@ -1002,78 +1125,7 @@ config VIDEO_S5P_MIPI_CSIS
 
 source "drivers/media/video/s5p-tv/Kconfig"
 
-#
-# USB Multimedia device configuration
-#
-
-menuconfig V4L_USB_DRIVERS
-       bool "V4L USB devices"
-       depends on USB
-       default y
-
-if V4L_USB_DRIVERS && USB
-
-source "drivers/media/video/uvc/Kconfig"
-
-source "drivers/media/video/gspca/Kconfig"
-
-source "drivers/media/video/pvrusb2/Kconfig"
-
-source "drivers/media/video/hdpvr/Kconfig"
-
-source "drivers/media/video/em28xx/Kconfig"
-
-source "drivers/media/video/tlg2300/Kconfig"
-
-source "drivers/media/video/cx231xx/Kconfig"
-
-source "drivers/media/video/tm6000/Kconfig"
-
-source "drivers/media/video/usbvision/Kconfig"
-
-source "drivers/media/video/et61x251/Kconfig"
-
-source "drivers/media/video/sn9c102/Kconfig"
-
-source "drivers/media/video/pwc/Kconfig"
-
-config USB_ZR364XX
-       tristate "USB ZR364XX Camera support"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_GEN
-       select VIDEOBUF_VMALLOC
-       ---help---
-         Say Y here if you want to connect this type of camera to your
-         computer's USB port.
-         See <file:Documentation/video4linux/zr364xx.txt> for more info
-         and list of supported cameras.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr364xx.
-
-config USB_STKWEBCAM
-       tristate "USB Syntek DC1125 Camera support"
-       depends on VIDEO_V4L2 && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to use this type of camera.
-         Supported devices are typically found in some Asus laptops,
-         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
-         may be supported by the stk11xx driver, from which this is
-         derived, see <http://sourceforge.net/projects/syntekdriver/>
-
-         To compile this driver as a module, choose M here: the
-         module will be called stkwebcam.
-
-config USB_S2255
-       tristate "USB Sensoray 2255 video capture device"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_VMALLOC
-       default n
-       help
-         Say Y here if you want support for the Sensoray 2255 USB device.
-         This driver can be compiled as a module, called s2255drv.
-
-endif # V4L_USB_DRIVERS
+endif # V4L_PLATFORM_DRIVERS
 endif # VIDEO_CAPTURE_DRIVERS
 
 menuconfig V4L_MEM2MEM_DRIVERS
@@ -1098,6 +1150,23 @@ config VIDEO_MEM2MEM_TESTDEV
          This is a virtual test device for the memory-to-memory driver
          framework.
 
+config VIDEO_SAMSUNG_S5P_G2D
+       tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       default n
+       ---help---
+         This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D
+         2d graphics accelerator.
+
+config VIDEO_SAMSUNG_S5P_JPEG
+       tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       ---help---
+         This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
 
 config VIDEO_SAMSUNG_S5P_MFC
        tristate "Samsung S5P MFC 5.1 Video Codec"
index 117f9c4b4cb9a9d804f96f7d80c2a125d857fb44..354138804cdad917e9b858f9724e5fe57f39b4f1 100644 (file)
@@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_NOON010PC30)       += noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
 obj-$(CONFIG_VIDEO_S5K6AA)     += s5k6aa.o
 obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
+obj-$(CONFIG_VIDEO_AS3645A)    += as3645a.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
@@ -177,9 +178,12 @@ obj-$(CONFIG_VIDEO_OMAP1)          += omap1_camera.o
 obj-$(CONFIG_VIDEO_ATMEL_ISI)          += atmel-isi.o
 
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)   += s5p-jpeg/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)    += s5p-mfc/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)     += s5p-tv/
 
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)    += s5p-g2d/
+
 obj-$(CONFIG_ARCH_DAVINCI)             += davinci/
 
 obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
index 23ba5c37c3e4d493bd243ddf444404fd43cd01e3..879f1d839760a5588376358c81128ededa8cee81 100644 (file)
@@ -64,6 +64,11 @@ static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd)
 
 static char *inputs[] = { "pass_through", "play_back" };
 
+static enum v4l2_mbus_pixelcode adv7170_codes[] = {
+       V4L2_MBUS_FMT_UYVY8_2X8,
+       V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -258,6 +263,60 @@ static int adv7170_s_routing(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+                               enum v4l2_mbus_pixelcode *code)
+{
+       if (index >= ARRAY_SIZE(adv7170_codes))
+               return -EINVAL;
+
+       *code = adv7170_codes[index];
+       return 0;
+}
+
+static int adv7170_g_fmt(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_framefmt *mf)
+{
+       u8 val = adv7170_read(sd, 0x7);
+
+       if ((val & 0x40) == (1 << 6))
+               mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+       else
+               mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+       mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
+       mf->width       = 0;
+       mf->height      = 0;
+       mf->field       = V4L2_FIELD_ANY;
+
+       return 0;
+}
+
+static int adv7170_s_fmt(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_framefmt *mf)
+{
+       u8 val = adv7170_read(sd, 0x7);
+       int ret;
+
+       switch (mf->code) {
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               val &= ~0x40;
+               break;
+
+       case V4L2_MBUS_FMT_UYVY8_1X16:
+               val |= 0x40;
+               break;
+
+       default:
+               v4l2_dbg(1, debug, sd,
+                       "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+               return -EINVAL;
+       }
+
+       ret = adv7170_write(sd, 0x7, val);
+
+       return ret;
+}
+
 static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -274,6 +333,9 @@ static const struct v4l2_subdev_core_ops adv7170_core_ops = {
 static const struct v4l2_subdev_video_ops adv7170_video_ops = {
        .s_std_output = adv7170_s_std_output,
        .s_routing = adv7170_s_routing,
+       .s_mbus_fmt = adv7170_s_fmt,
+       .g_mbus_fmt = adv7170_g_fmt,
+       .enum_mbus_fmt  = adv7170_enum_fmt,
 };
 
 static const struct v4l2_subdev_ops adv7170_ops = {
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c
new file mode 100644 (file)
index 0000000..ec859a5
--- /dev/null
@@ -0,0 +1,904 @@
+/*
+ * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver
+ *
+ * Copyright (C) 2008-2011 Nokia Corporation
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - Check hardware FSTROBE control when sensor driver add support for this
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <media/as3645a.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#define AS_TIMER_MS_TO_CODE(t)                 (((t) - 100) / 50)
+#define AS_TIMER_CODE_TO_MS(c)                 (50 * (c) + 100)
+
+/* Register definitions */
+
+/* Read-only Design info register: Reset state: xxxx 0001 */
+#define AS_DESIGN_INFO_REG                     0x00
+#define AS_DESIGN_INFO_FACTORY(x)              (((x) >> 4))
+#define AS_DESIGN_INFO_MODEL(x)                        ((x) & 0x0f)
+
+/* Read-only Version control register: Reset state: 0000 0000
+ * for first engineering samples
+ */
+#define AS_VERSION_CONTROL_REG                 0x01
+#define AS_VERSION_CONTROL_RFU(x)              (((x) >> 4))
+#define AS_VERSION_CONTROL_VERSION(x)          ((x) & 0x0f)
+
+/* Read / Write        (Indicator and timer register): Reset state: 0000 1111 */
+#define AS_INDICATOR_AND_TIMER_REG             0x02
+#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT   0
+#define AS_INDICATOR_AND_TIMER_VREF_SHIFT      4
+#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
+
+/* Read / Write        (Current set register): Reset state: 0110 1001 */
+#define AS_CURRENT_SET_REG                     0x03
+#define AS_CURRENT_ASSIST_LIGHT_SHIFT          0
+#define AS_CURRENT_LED_DET_ON                  (1 << 3)
+#define AS_CURRENT_FLASH_CURRENT_SHIFT         4
+
+/* Read / Write        (Control register): Reset state: 1011 0100 */
+#define AS_CONTROL_REG                         0x04
+#define AS_CONTROL_MODE_SETTING_SHIFT          0
+#define AS_CONTROL_STROBE_ON                   (1 << 2)
+#define AS_CONTROL_OUT_ON                      (1 << 3)
+#define AS_CONTROL_EXT_TORCH_ON                        (1 << 4)
+#define AS_CONTROL_STROBE_TYPE_EDGE            (0 << 5)
+#define AS_CONTROL_STROBE_TYPE_LEVEL           (1 << 5)
+#define AS_CONTROL_COIL_PEAK_SHIFT             6
+
+/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
+#define AS_FAULT_INFO_REG                      0x05
+#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT      (1 << 1)
+#define AS_FAULT_INFO_INDICATOR_LED            (1 << 2)
+#define AS_FAULT_INFO_LED_AMOUNT               (1 << 3)
+#define AS_FAULT_INFO_TIMEOUT                  (1 << 4)
+#define AS_FAULT_INFO_OVER_TEMPERATURE         (1 << 5)
+#define AS_FAULT_INFO_SHORT_CIRCUIT            (1 << 6)
+#define AS_FAULT_INFO_OVER_VOLTAGE             (1 << 7)
+
+/* Boost register */
+#define AS_BOOST_REG                           0x0d
+#define AS_BOOST_CURRENT_DISABLE               (0 << 0)
+#define AS_BOOST_CURRENT_ENABLE                        (1 << 0)
+
+/* Password register is used to unlock boost register writing */
+#define AS_PASSWORD_REG                                0x0f
+#define AS_PASSWORD_UNLOCK_VALUE               0x55
+
+enum as_mode {
+       AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
+       AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
+       AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
+       AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
+};
+
+/*
+ * struct as3645a
+ *
+ * @subdev:            V4L2 subdev
+ * @pdata:             Flash platform data
+ * @power_lock:                Protects power_count
+ * @power_count:       Power reference count
+ * @led_mode:          V4L2 flash LED mode
+ * @timeout:           Flash timeout in microseconds
+ * @flash_current:     Flash current (0=200mA ... 15=500mA). Maximum
+ *                     values are 400mA for two LEDs and 500mA for one LED.
+ * @assist_current:    Torch/Assist light current (0=20mA, 1=40mA ... 7=160mA)
+ * @indicator_current: Indicator LED current (0=0mA, 1=2.5mA ... 4=10mA)
+ * @strobe_source:     Flash strobe source (software or external)
+ */
+struct as3645a {
+       struct v4l2_subdev subdev;
+       const struct as3645a_platform_data *pdata;
+
+       struct mutex power_lock;
+       int power_count;
+
+       /* Controls */
+       struct v4l2_ctrl_handler ctrls;
+
+       enum v4l2_flash_led_mode led_mode;
+       unsigned int timeout;
+       u8 flash_current;
+       u8 assist_current;
+       u8 indicator_current;
+       enum v4l2_flash_strobe_source strobe_source;
+};
+
+#define to_as3645a(sd) container_of(sd, struct as3645a, subdev)
+
+/* Return negative errno else zero on success */
+static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int rval;
+
+       rval = i2c_smbus_write_byte_data(client, addr, val);
+
+       dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
+               rval < 0 ? "fail" : "ok");
+
+       return rval;
+}
+
+/* Return negative errno else a data byte received from the device. */
+static int as3645a_read(struct as3645a *flash, u8 addr)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int rval;
+
+       rval = i2c_smbus_read_byte_data(client, addr);
+
+       dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
+               rval < 0 ? "fail" : "ok");
+
+       return rval;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration and trigger
+ */
+
+/*
+ * as3645a_set_config - Set flash configuration registers
+ * @flash: The flash
+ *
+ * Configure the hardware with flash, assist and indicator currents, as well as
+ * flash timeout.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int as3645a_set_config(struct as3645a *flash)
+{
+       int ret;
+       u8 val;
+
+       val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
+           | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
+           | AS_CURRENT_LED_DET_ON;
+
+       ret = as3645a_write(flash, AS_CURRENT_SET_REG, val);
+       if (ret < 0)
+               return ret;
+
+       val = AS_TIMER_MS_TO_CODE(flash->timeout / 1000)
+                   << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
+
+       val |= (flash->pdata->vref << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
+           |  ((flash->indicator_current ? flash->indicator_current - 1 : 0)
+                << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
+
+       return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
+}
+
+/*
+ * as3645a_set_control - Set flash control register
+ * @flash: The flash
+ * @mode: Desired output mode
+ * @on: Desired output state
+ *
+ * Configure the hardware with output mode and state.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int
+as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
+{
+       u8 reg;
+
+       /* Configure output parameters and operation mode. */
+       reg = (flash->pdata->peak << AS_CONTROL_COIL_PEAK_SHIFT)
+           | (on ? AS_CONTROL_OUT_ON : 0)
+           | mode;
+
+       if (flash->led_mode == V4L2_FLASH_LED_MODE_FLASH &&
+           flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL) {
+               reg |= AS_CONTROL_STROBE_TYPE_LEVEL
+                   |  AS_CONTROL_STROBE_ON;
+       }
+
+       return as3645a_write(flash, AS_CONTROL_REG, reg);
+}
+
+/*
+ * as3645a_set_output - Configure output and operation mode
+ * @flash: Flash controller
+ * @strobe: Strobe the flash (only valid in flash mode)
+ *
+ * Turn the LEDs output on/off and set the operation mode based on the current
+ * parameters.
+ *
+ * The AS3645A can't control the indicator LED independently of the flash/torch
+ * LED. If the flash controller is in V4L2_FLASH_LED_MODE_NONE mode, set the
+ * chip to indicator mode. Otherwise set it to assist light (torch) or flash
+ * mode.
+ *
+ * In indicator and assist modes, turn the output on/off based on the indicator
+ * and torch currents. In software strobe flash mode, turn the output on/off
+ * based on the strobe parameter.
+ */
+static int as3645a_set_output(struct as3645a *flash, bool strobe)
+{
+       enum as_mode mode;
+       bool on;
+
+       switch (flash->led_mode) {
+       case V4L2_FLASH_LED_MODE_NONE:
+               on = flash->indicator_current != 0;
+               mode = AS_MODE_INDICATOR;
+               break;
+       case V4L2_FLASH_LED_MODE_TORCH:
+               on = true;
+               mode = AS_MODE_ASSIST;
+               break;
+       case V4L2_FLASH_LED_MODE_FLASH:
+               on = strobe;
+               mode = AS_MODE_FLASH;
+               break;
+       default:
+               BUG();
+       }
+
+       /* Configure output parameters and operation mode. */
+       return as3645a_set_control(flash, mode, on);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int as3645a_is_active(struct as3645a *flash)
+{
+       int ret;
+
+       ret = as3645a_read(flash, AS_CONTROL_REG);
+       return ret < 0 ? ret : !!(ret & AS_CONTROL_OUT_ON);
+}
+
+static int as3645a_read_fault(struct as3645a *flash)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int rval;
+
+       /* NOTE: reading register clear fault status */
+       rval = as3645a_read(flash, AS_FAULT_INFO_REG);
+       if (rval < 0)
+               return rval;
+
+       if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+               dev_dbg(&client->dev, "Inductor Peak limit fault\n");
+
+       if (rval & AS_FAULT_INFO_INDICATOR_LED)
+               dev_dbg(&client->dev, "Indicator LED fault: "
+                       "Short circuit or open loop\n");
+
+       dev_dbg(&client->dev, "%u connected LEDs\n",
+               rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
+
+       if (rval & AS_FAULT_INFO_TIMEOUT)
+               dev_dbg(&client->dev, "Timeout fault\n");
+
+       if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
+               dev_dbg(&client->dev, "Over temperature fault\n");
+
+       if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
+               dev_dbg(&client->dev, "Short circuit fault\n");
+
+       if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
+               dev_dbg(&client->dev, "Over voltage fault: "
+                       "Indicates missing capacitor or open connection\n");
+
+       return rval;
+}
+
+static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct as3645a *flash =
+               container_of(ctrl->handler, struct as3645a, ctrls);
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int value;
+
+       switch (ctrl->id) {
+       case V4L2_CID_FLASH_FAULT:
+               value = as3645a_read_fault(flash);
+               if (value < 0)
+                       return value;
+
+               ctrl->cur.val = 0;
+               if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+               if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+               if (value & AS_FAULT_INFO_TIMEOUT)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+               if (value & AS_FAULT_INFO_OVER_VOLTAGE)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+               if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
+               if (value & AS_FAULT_INFO_INDICATOR_LED)
+                       ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
+               break;
+
+       case V4L2_CID_FLASH_STROBE_STATUS:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
+                       ctrl->cur.val = 0;
+                       break;
+               }
+
+               value = as3645a_is_active(flash);
+               if (value < 0)
+                       return value;
+
+               ctrl->cur.val = value;
+               break;
+       }
+
+       dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
+
+       return 0;
+}
+
+static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct as3645a *flash =
+               container_of(ctrl->handler, struct as3645a, ctrls);
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int ret;
+
+       dev_dbg(&client->dev, "S_CTRL %08x:%d\n", ctrl->id, ctrl->val);
+
+       /* If a control that doesn't apply to the current mode is modified,
+        * we store the value and return immediately. The setting will be
+        * applied when the LED mode is changed. Otherwise we apply the setting
+        * immediately.
+        */
+
+       switch (ctrl->id) {
+       case V4L2_CID_FLASH_LED_MODE:
+               if (flash->indicator_current)
+                       return -EBUSY;
+
+               ret = as3645a_set_config(flash);
+               if (ret < 0)
+                       return ret;
+
+               flash->led_mode = ctrl->val;
+               return as3645a_set_output(flash, false);
+
+       case V4L2_CID_FLASH_STROBE_SOURCE:
+               flash->strobe_source = ctrl->val;
+
+               /* Applies to flash mode only. */
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       break;
+
+               return as3645a_set_output(flash, false);
+
+       case V4L2_CID_FLASH_STROBE:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       return -EBUSY;
+
+               return as3645a_set_output(flash, true);
+
+       case V4L2_CID_FLASH_STROBE_STOP:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       return -EBUSY;
+
+               return as3645a_set_output(flash, false);
+
+       case V4L2_CID_FLASH_TIMEOUT:
+               flash->timeout = ctrl->val;
+
+               /* Applies to flash mode only. */
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       break;
+
+               return as3645a_set_config(flash);
+
+       case V4L2_CID_FLASH_INTENSITY:
+               flash->flash_current = (ctrl->val - AS3645A_FLASH_INTENSITY_MIN)
+                                    / AS3645A_FLASH_INTENSITY_STEP;
+
+               /* Applies to flash mode only. */
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       break;
+
+               return as3645a_set_config(flash);
+
+       case V4L2_CID_FLASH_TORCH_INTENSITY:
+               flash->assist_current =
+                       (ctrl->val - AS3645A_TORCH_INTENSITY_MIN)
+                       / AS3645A_TORCH_INTENSITY_STEP;
+
+               /* Applies to torch mode only. */
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_TORCH)
+                       break;
+
+               return as3645a_set_config(flash);
+
+       case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_NONE)
+                       return -EBUSY;
+
+               flash->indicator_current =
+                       (ctrl->val - AS3645A_INDICATOR_INTENSITY_MIN)
+                       / AS3645A_INDICATOR_INTENSITY_STEP;
+
+               ret = as3645a_set_config(flash);
+               if (ret < 0)
+                       return ret;
+
+               if ((ctrl->val == 0) == (ctrl->cur.val == 0))
+                       break;
+
+               return as3645a_set_output(flash, false);
+       }
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops as3645a_ctrl_ops = {
+       .g_volatile_ctrl = as3645a_get_ctrl,
+       .s_ctrl = as3645a_set_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+/* Put device into know state. */
+static int as3645a_setup(struct as3645a *flash)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+       int ret;
+
+       /* clear errors */
+       ret = as3645a_read(flash, AS_FAULT_INFO_REG);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&client->dev, "Fault info: %02x\n", ret);
+
+       ret = as3645a_set_config(flash);
+       if (ret < 0)
+               return ret;
+
+       ret = as3645a_set_output(flash, false);
+       if (ret < 0)
+               return ret;
+
+       /* read status */
+       ret = as3645a_read_fault(flash);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&client->dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
+               as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
+       dev_dbg(&client->dev, "AS_CURRENT_SET_REG: %02x\n",
+               as3645a_read(flash, AS_CURRENT_SET_REG));
+       dev_dbg(&client->dev, "AS_CONTROL_REG: %02x\n",
+               as3645a_read(flash, AS_CONTROL_REG));
+
+       return ret & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
+}
+
+static int __as3645a_set_power(struct as3645a *flash, int on)
+{
+       int ret;
+
+       if (!on)
+               as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
+
+       if (flash->pdata->set_power) {
+               ret = flash->pdata->set_power(&flash->subdev, on);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (!on)
+               return 0;
+
+       ret = as3645a_setup(flash);
+       if (ret < 0) {
+               if (flash->pdata->set_power)
+                       flash->pdata->set_power(&flash->subdev, 0);
+       }
+
+       return ret;
+}
+
+static int as3645a_set_power(struct v4l2_subdev *sd, int on)
+{
+       struct as3645a *flash = to_as3645a(sd);
+       int ret = 0;
+
+       mutex_lock(&flash->power_lock);
+
+       if (flash->power_count == !on) {
+               ret = __as3645a_set_power(flash, !!on);
+               if (ret < 0)
+                       goto done;
+       }
+
+       flash->power_count += on ? 1 : -1;
+       WARN_ON(flash->power_count < 0);
+
+done:
+       mutex_unlock(&flash->power_lock);
+       return ret;
+}
+
+static int as3645a_registered(struct v4l2_subdev *sd)
+{
+       struct as3645a *flash = to_as3645a(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int rval, man, model, rfu, version;
+       const char *vendor;
+
+       /* Power up the flash driver and read manufacturer ID, model ID, RFU
+        * and version.
+        */
+       rval = as3645a_set_power(&flash->subdev, 1);
+       if (rval < 0)
+               return rval;
+
+       rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
+       if (rval < 0)
+               goto power_off;
+
+       man = AS_DESIGN_INFO_FACTORY(rval);
+       model = AS_DESIGN_INFO_MODEL(rval);
+
+       rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
+       if (rval < 0)
+               goto power_off;
+
+       rfu = AS_VERSION_CONTROL_RFU(rval);
+       version = AS_VERSION_CONTROL_VERSION(rval);
+
+       /* Verify the chip model and version. */
+       if (model != 0x01 || rfu != 0x00) {
+               dev_err(&client->dev, "AS3645A not detected "
+                       "(model %d rfu %d)\n", model, rfu);
+               rval = -ENODEV;
+               goto power_off;
+       }
+
+       switch (man) {
+       case 1:
+               vendor = "AMS, Austria Micro Systems";
+               break;
+       case 2:
+               vendor = "ADI, Analog Devices Inc.";
+               break;
+       case 3:
+               vendor = "NSC, National Semiconductor";
+               break;
+       case 4:
+               vendor = "NXP";
+               break;
+       case 5:
+               vendor = "TI, Texas Instrument";
+               break;
+       default:
+               vendor = "Unknown";
+       }
+
+       dev_info(&client->dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
+                man, version);
+
+       rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
+       if (rval < 0)
+               goto power_off;
+
+       rval = as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
+       if (rval < 0)
+               goto power_off;
+
+       /* Setup default values. This makes sure that the chip is in a known
+        * state, in case the power rail can't be controlled.
+        */
+       rval = as3645a_setup(flash);
+
+power_off:
+       as3645a_set_power(&flash->subdev, 0);
+
+       return rval;
+}
+
+static int as3645a_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       return as3645a_set_power(sd, 1);
+}
+
+static int as3645a_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       return as3645a_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops as3645a_core_ops = {
+       .s_power                = as3645a_set_power,
+};
+
+static const struct v4l2_subdev_ops as3645a_ops = {
+       .core = &as3645a_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops as3645a_internal_ops = {
+       .registered = as3645a_registered,
+       .open = as3645a_open,
+       .close = as3645a_close,
+};
+
+/* -----------------------------------------------------------------------------
+ *  I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int as3645a_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct as3645a *flash = to_as3645a(subdev);
+       int rval;
+
+       if (flash->power_count == 0)
+               return 0;
+
+       rval = __as3645a_set_power(flash, 0);
+
+       dev_dbg(&client->dev, "Suspend %s\n", rval < 0 ? "failed" : "ok");
+
+       return rval;
+}
+
+static int as3645a_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct as3645a *flash = to_as3645a(subdev);
+       int rval;
+
+       if (flash->power_count == 0)
+               return 0;
+
+       rval = __as3645a_set_power(flash, 1);
+
+       dev_dbg(&client->dev, "Resume %s\n", rval < 0 ? "fail" : "ok");
+
+       return rval;
+}
+
+#else
+
+#define as3645a_suspend        NULL
+#define as3645a_resume NULL
+
+#endif /* CONFIG_PM */
+
+/*
+ * as3645a_init_controls - Create controls
+ * @flash: The flash
+ *
+ * The number of LEDs reported in platform data is used to compute default
+ * limits. Parameters passed through platform data can override those limits.
+ */
+static int as3645a_init_controls(struct as3645a *flash)
+{
+       const struct as3645a_platform_data *pdata = flash->pdata;
+       struct v4l2_ctrl *ctrl;
+       int maximum;
+
+       v4l2_ctrl_handler_init(&flash->ctrls, 10);
+
+       /* V4L2_CID_FLASH_LED_MODE */
+       v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+                              V4L2_CID_FLASH_LED_MODE, 2, ~7,
+                              V4L2_FLASH_LED_MODE_NONE);
+
+       /* V4L2_CID_FLASH_STROBE_SOURCE */
+       v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+                              V4L2_CID_FLASH_STROBE_SOURCE,
+                              pdata->ext_strobe ? 1 : 0,
+                              pdata->ext_strobe ? ~3 : ~1,
+                              V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
+
+       flash->strobe_source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
+
+       /* V4L2_CID_FLASH_STROBE */
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+
+       /* V4L2_CID_FLASH_STROBE_STOP */
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+
+       /* V4L2_CID_FLASH_STROBE_STATUS */
+       ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                                V4L2_CID_FLASH_STROBE_STATUS, 0, 1, 1, 1);
+       if (ctrl != NULL)
+               ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+       /* V4L2_CID_FLASH_TIMEOUT */
+       maximum = pdata->timeout_max;
+
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_TIMEOUT, AS3645A_FLASH_TIMEOUT_MIN,
+                         maximum, AS3645A_FLASH_TIMEOUT_STEP, maximum);
+
+       flash->timeout = maximum;
+
+       /* V4L2_CID_FLASH_INTENSITY */
+       maximum = pdata->flash_max_current;
+
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_INTENSITY, AS3645A_FLASH_INTENSITY_MIN,
+                         maximum, AS3645A_FLASH_INTENSITY_STEP, maximum);
+
+       flash->flash_current = (maximum - AS3645A_FLASH_INTENSITY_MIN)
+                            / AS3645A_FLASH_INTENSITY_STEP;
+
+       /* V4L2_CID_FLASH_TORCH_INTENSITY */
+       maximum = pdata->torch_max_current;
+
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_TORCH_INTENSITY,
+                         AS3645A_TORCH_INTENSITY_MIN, maximum,
+                         AS3645A_TORCH_INTENSITY_STEP,
+                         AS3645A_TORCH_INTENSITY_MIN);
+
+       flash->assist_current = 0;
+
+       /* V4L2_CID_FLASH_INDICATOR_INTENSITY */
+       v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                         V4L2_CID_FLASH_INDICATOR_INTENSITY,
+                         AS3645A_INDICATOR_INTENSITY_MIN,
+                         AS3645A_INDICATOR_INTENSITY_MAX,
+                         AS3645A_INDICATOR_INTENSITY_STEP,
+                         AS3645A_INDICATOR_INTENSITY_MIN);
+
+       flash->indicator_current = 0;
+
+       /* V4L2_CID_FLASH_FAULT */
+       ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+                                V4L2_CID_FLASH_FAULT, 0,
+                                V4L2_FLASH_FAULT_OVER_VOLTAGE |
+                                V4L2_FLASH_FAULT_TIMEOUT |
+                                V4L2_FLASH_FAULT_OVER_TEMPERATURE |
+                                V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+       if (ctrl != NULL)
+               ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+       flash->subdev.ctrl_handler = &flash->ctrls;
+
+       return flash->ctrls.error;
+}
+
+static int as3645a_probe(struct i2c_client *client,
+                        const struct i2c_device_id *devid)
+{
+       struct as3645a *flash;
+       int ret;
+
+       if (client->dev.platform_data == NULL)
+               return -ENODEV;
+
+       flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+       if (flash == NULL)
+               return -ENOMEM;
+
+       flash->pdata = client->dev.platform_data;
+
+       v4l2_i2c_subdev_init(&flash->subdev, client, &as3645a_ops);
+       flash->subdev.internal_ops = &as3645a_internal_ops;
+       flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       ret = as3645a_init_controls(flash);
+       if (ret < 0)
+               goto done;
+
+       ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+       if (ret < 0)
+               goto done;
+
+       flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+       mutex_init(&flash->power_lock);
+
+       flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+
+done:
+       if (ret < 0) {
+               v4l2_ctrl_handler_free(&flash->ctrls);
+               kfree(flash);
+       }
+
+       return ret;
+}
+
+static int __exit as3645a_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       struct as3645a *flash = to_as3645a(subdev);
+
+       v4l2_device_unregister_subdev(subdev);
+       v4l2_ctrl_handler_free(&flash->ctrls);
+       media_entity_cleanup(&flash->subdev.entity);
+       mutex_destroy(&flash->power_lock);
+       kfree(flash);
+
+       return 0;
+}
+
+static const struct i2c_device_id as3645a_id_table[] = {
+       { AS3645A_NAME, 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
+
+static const struct dev_pm_ops as3645a_pm_ops = {
+       .suspend = as3645a_suspend,
+       .resume = as3645a_resume,
+};
+
+static struct i2c_driver as3645a_i2c_driver = {
+       .driver = {
+               .name = AS3645A_NAME,
+               .pm   = &as3645a_pm_ops,
+       },
+       .probe  = as3645a_probe,
+       .remove = __exit_p(as3645a_remove),
+       .id_table = as3645a_id_table,
+};
+
+static int __init as3645a_init(void)
+{
+       int rval;
+
+       rval = i2c_add_driver(&as3645a_i2c_driver);
+       if (rval)
+               pr_err("%s: Failed to register the driver\n", AS3645A_NAME);
+
+       return rval;
+}
+
+static void __exit as3645a_exit(void)
+{
+       i2c_del_driver(&as3645a_i2c_driver);
+}
+
+module_init(as3645a_init);
+module_exit(as3645a_exit);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
+MODULE_LICENSE("GPL");
index 8c775c59e120f30589d520c49d75b18fd9a397fa..9fe4519176a4850ceecda1d29fb961eeb7b03fb2 100644 (file)
@@ -90,7 +90,10 @@ struct atmel_isi {
        struct isi_dma_desc             dma_desc[MAX_BUFFER_NUM];
 
        struct completion               complete;
+       /* ISI peripherial clock */
        struct clk                      *pclk;
+       /* ISI_MCK, feed to camera sensor to generate pixel clock */
+       struct clk                      *mck;
        unsigned int                    irq;
 
        struct isi_platform_data        *pdata;
@@ -766,6 +769,12 @@ static int isi_camera_add_device(struct soc_camera_device *icd)
        if (ret)
                return ret;
 
+       ret = clk_enable(isi->mck);
+       if (ret) {
+               clk_disable(isi->pclk);
+               return ret;
+       }
+
        isi->icd = icd;
        dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n",
                 icd->devnum);
@@ -779,6 +788,7 @@ static void isi_camera_remove_device(struct soc_camera_device *icd)
 
        BUG_ON(icd != isi->icd);
 
+       clk_disable(isi->mck);
        clk_disable(isi->pclk);
        isi->icd = NULL;
 
@@ -803,7 +813,7 @@ static int isi_camera_querycap(struct soc_camera_host *ici,
        return 0;
 }
 
-static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
+static int isi_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -874,7 +884,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
 
        if (isi->pdata->has_emb_sync)
                cfg1 |= ISI_CFG1_EMB_SYNC;
-       if (isi->pdata->isi_full_mode)
+       if (isi->pdata->full_mode)
                cfg1 |= ISI_CFG1_FULL_MODE;
 
        isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -912,6 +922,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev)
                        isi->fb_descriptors_phys);
 
        iounmap(isi->regs);
+       clk_put(isi->mck);
        clk_put(isi->pclk);
        kfree(isi);
 
@@ -930,7 +941,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
        struct isi_platform_data *pdata;
 
        pdata = dev->platform_data;
-       if (!pdata || !pdata->data_width_flags) {
+       if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) {
                dev_err(&pdev->dev,
                        "No config available for Atmel ISI\n");
                return -EINVAL;
@@ -959,6 +970,19 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&isi->video_buffer_list);
        INIT_LIST_HEAD(&isi->dma_desc_head);
 
+       /* Get ISI_MCK, provided by programmable clock or external clock */
+       isi->mck = clk_get(dev, "isi_mck");
+       if (IS_ERR(isi->mck)) {
+               dev_err(dev, "Failed to get isi_mck\n");
+               ret = PTR_ERR(isi->mck);
+               goto err_clk_get;
+       }
+
+       /* Set ISI_MCK's frequency, it should be faster than pixel clock */
+       ret = clk_set_rate(isi->mck, pdata->mck_hz);
+       if (ret < 0)
+               goto err_set_mck_rate;
+
        isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
                                sizeof(struct fbd) * MAX_BUFFER_NUM,
                                &isi->fb_descriptors_phys,
@@ -1034,9 +1058,12 @@ err_alloc_ctx:
                        isi->p_fb_descriptors,
                        isi->fb_descriptors_phys);
 err_alloc_descriptors:
+err_set_mck_rate:
+       clk_put(isi->mck);
+err_clk_get:
        kfree(isi);
 err_alloc_isi:
-       clk_put(isi->pclk);
+       clk_put(pclk);
 
        return ret;
 }
index 0c3a5ba0e857d85b8a657c476e2f36aaf509eb01..81ba9d9d1b52c2024d1777e0ff4e730393063124 100644 (file)
@@ -2,6 +2,7 @@
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
        depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
+       depends on DVB_CAPTURE_DRIVERS
        select I2C_ALGOBIT
        select VIDEO_TVEEPROM
        select VIDEOBUF_VMALLOC
index cbdb65c34f219081387fce62731b1f74e0b05f41..05c299fa5d79f5c90de3da3eca758ad45f7f2933 100644 (file)
@@ -348,7 +348,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
        }
 }
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int au0828_i2c_register(struct au0828_dev *dev)
 {
        dprintk(1, "%s()\n", __func__);
index 0bcd95303bb0c2ace9c55d21e95eb530cbdfe000..c37e6acffdedef6ea698f73da153a3f9ec47f3d7 100644 (file)
 #ifndef PCI_DEVICE_ID_BT849
 #define PCI_DEVICE_ID_BT849     0x351
 #endif
+#ifndef PCI_DEVICE_ID_FUSION879
+#define PCI_DEVICE_ID_FUSION879        0x36c
+#endif
+
 #ifndef PCI_DEVICE_ID_BT878
 #define PCI_DEVICE_ID_BT878     0x36e
 #endif
@@ -37,7 +41,6 @@
 #define PCI_DEVICE_ID_BT879     0x36f
 #endif
 
-
 /* Brooktree 848 registers */
 
 #define BT848_DSTATUS          0x000
index 5939021d8eba4782cc983e99b658d0f370c93c0a..ff2933ab705ff2608dd38827dcab12ff0b0ca2ee 100644 (file)
@@ -80,6 +80,8 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input);
 static void gv800s_muxsel(struct bttv *btv, unsigned int input);
 static void gv800s_init(struct bttv *btv);
 
+static void td3116_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);
@@ -284,7 +286,8 @@ static struct CARD {
        { 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
        { 0x217d6606, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
        { 0xfff6f6ff, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
-       { 0x03116000, BTTV_BOARD_SENSORAY311,   "Sensoray 311" },
+       { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" },
+       { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" },
        { 0x00790e11, BTTV_BOARD_WINDVR,        "Canopus WinDVR PCI" },
        { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX,       "Face to Face Tvmax" },
        { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" },
@@ -341,6 +344,7 @@ static struct CARD {
        { 0x15401835, BTTV_BOARD_PV183,         "Provideo PV183-6" },
        { 0x15401836, BTTV_BOARD_PV183,         "Provideo PV183-7" },
        { 0x15401837, BTTV_BOARD_PV183,         "Provideo PV183-8" },
+       { 0x3116f200, BTTV_BOARD_TVT_TD3116,    "Tongwei Video Technology TD-3116" },
 
        { 0, -1, NULL }
 };
@@ -1526,10 +1530,10 @@ struct tvcard bttv_tvcards[] = {
                        GPIO20,22,23: R30,R29,R28
                */
        },
-       [BTTV_BOARD_SENSORAY311] = {
+       [BTTV_BOARD_SENSORAY311_611] = {
                /* Clay Kunz <ckunz@mail.arc.nasa.gov> */
-               /* you must jumper JP5 for the card to work */
-               .name           = "Sensoray 311",
+               /* you must jumper JP5 for the 311 card (PC/104+) to work */
+               .name           = "Sensoray 311/611",
                .video_inputs   = 5,
                /* .audio_inputs= 0, */
                .svhs           = 4,
@@ -2879,6 +2883,16 @@ struct tvcard bttv_tvcards[] = {
                .tuner_type     = TUNER_ABSENT,
                .tuner_addr     = ADDR_UNSET,
        },
+       [BTTV_BOARD_TVT_TD3116] = {
+               .name           = "Tongwei Video Technology TD-3116",
+               .video_inputs   = 16,
+               .gpiomask       = 0xc00ff,
+               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+               .muxsel_hook    = td3116_muxsel,
+               .svhs           = NO_SVHS,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+       },
 };
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3228,6 +3242,42 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input)
        gpio_bits(0xf, inmux);
 }
 
+/*
+ * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878.
+ * The first 74HC4051 has the lower 8 inputs, the second one the higher 8.
+ * The muxes are controlled via a 74HC373 latch which is connected to
+ * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch.
+ * Q0 of the latch is connected to the Enable (~E) input of the first
+ * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051.
+ * Q4 - Q7 are connected to the second 74HC4051 in the same way.
+ */
+
+static void td3116_latch_value(struct bttv *btv, u32 value)
+{
+       gpio_bits((1<<18) | 0xff, value);
+       gpio_bits((1<<18) | 0xff, (1<<18) | value);
+       udelay(1);
+       gpio_bits((1<<18) | 0xff, value);
+}
+
+static void td3116_muxsel(struct bttv *btv, unsigned int input)
+{
+       u32 value;
+       u32 highbit;
+
+       highbit = (input & 0x8) >> 3 ;
+
+       /* Disable outputs and set value in the mux */
+       value = 0x11; /* Disable outputs */
+       value |= ((input & 0x7) << 1)  << (4 * highbit);
+       td3116_latch_value(btv, value);
+
+       /* Enable the correct output */
+       value &= ~0x11;
+       value |= ((highbit ^ 0x1) << 4) | highbit;
+       td3116_latch_value(btv, value);
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void bttv_reset_audio(struct bttv *btv)
index 3dd06607aec2a0457ec4b75a36463162ab15b6e4..76c301f05095375ec21d6956d00a9d69f8b33da6 100644 (file)
@@ -4572,6 +4572,7 @@ static struct pci_device_id bttv_pci_tbl[] = {
        {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
        {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
        {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
        {0,}
 };
 
index e3952af7e56e2df0f28c6be896add69e2fa37b0f..580c8e682392c4c5524c789c8b21a75fbbe23314 100644 (file)
@@ -346,7 +346,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
        }
 }
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int __devinit init_bttv_i2c(struct bttv *btv)
 {
        strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
index c6333595c6b90a3749fabfa8e3f90de1751fa2c3..c5171619ac7998369511c515da9046beda33d315 100644 (file)
@@ -96,7 +96,7 @@
 #define BTTV_BOARD_PV_BT878P_PLUS          0x46
 #define BTTV_BOARD_FLYVIDEO98EZ            0x47
 #define BTTV_BOARD_PV_BT878P_9B            0x48
-#define BTTV_BOARD_SENSORAY311             0x49
+#define BTTV_BOARD_SENSORAY311_611         0x49
 #define BTTV_BOARD_RV605                   0x4a
 #define BTTV_BOARD_POWERCLR_MTV878         0x4b
 #define BTTV_BOARD_WINDVR                  0x4c
 #define BTTV_BOARD_GEOVISION_GV800S       0x9d
 #define BTTV_BOARD_GEOVISION_GV800S_SL    0x9e
 #define BTTV_BOARD_PV183                   0x9f
+#define BTTV_BOARD_TVT_TD3116             0xa0
 
 
 /* more card-specific defines */
index 040aaa87579ddf0c21f4a9d786a8d636ac5ebfe0..51609d5c88ce7962d765f0e5a3ea66e74bd69946 100644 (file)
@@ -232,7 +232,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = {
        .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
 };
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int init_cx18_i2c(struct cx18 *cx)
 {
        int i, err;
index bdfd1921e30021062f8c1ddcd50f476f3bf8d513..1180fdc8d983b1b861edc635a7e9ed53463d56ee 100644 (file)
@@ -24,6 +24,6 @@
 int cx18_i2c_register(struct cx18 *cx, unsigned idx);
 struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int init_cx18_i2c(struct cx18 *cx);
 void exit_cx18_i2c(struct cx18 *cx);
index ae85a7a7bd73814c81b578761b522e7ddda9c8bf..446f692aabb740e175326f4017b925517f2ab52c 100644 (file)
@@ -40,10 +40,10 @@ config VIDEO_CX231XX_ALSA
 
 config VIDEO_CX231XX_DVB
        tristate "DVB/ATSC Support for Cx231xx based TV cards"
-       depends on VIDEO_CX231XX && DVB_CORE
+       depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS
        select VIDEOBUF_DVB
-       select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
        select DVB_MB86A20S if !DVB_FE_CUSTOMISE
 
        ---help---
index 30d13c15739a7d32a3a66636f90cb9aa4edde2df..a2c2b7d343ec6c05d7bee2f1e1015c9a25a649f6 100644 (file)
@@ -111,6 +111,9 @@ static void cx231xx_audio_isocirq(struct urb *urb)
        struct snd_pcm_substream *substream;
        struct snd_pcm_runtime *runtime;
 
+       if (dev->state & DEV_DISCONNECTED)
+               return;
+
        switch (urb->status) {
        case 0:         /* success */
        case -ETIMEDOUT:        /* NAK */
@@ -196,6 +199,9 @@ static void cx231xx_audio_bulkirq(struct urb *urb)
        struct snd_pcm_substream *substream;
        struct snd_pcm_runtime *runtime;
 
+       if (dev->state & DEV_DISCONNECTED)
+               return;
+
        switch (urb->status) {
        case 0:         /* success */
        case -ETIMEDOUT:        /* NAK */
@@ -273,6 +279,9 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
 
        cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
 
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
        sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
 
        for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -298,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
                urb->context = dev;
                urb->pipe = usb_rcvisocpipe(dev->udev,
                                                dev->adev.end_point_addr);
-               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
                urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->interval = 1;
                urb->complete = cx231xx_audio_isocirq;
@@ -331,6 +340,9 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
 
        cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
 
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
        sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
 
        for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -356,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
                urb->context = dev;
                urb->pipe = usb_rcvbulkpipe(dev->udev,
                                                dev->adev.end_point_addr);
-               urb->transfer_flags = 0;
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
                urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->complete = cx231xx_audio_bulkirq;
                urb->transfer_buffer_length = sb_size;
@@ -432,6 +444,11 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
                return -ENODEV;
        }
 
+       if (dev->state & DEV_DISCONNECTED) {
+               cx231xx_errdev("Can't open. the device was removed.\n");
+               return -ENODEV;
+       }
+
        /* Sets volume, mute, etc */
        dev->mute = 0;
 
@@ -571,6 +588,9 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
        struct cx231xx *dev = snd_pcm_substream_chip(substream);
        int retval;
 
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
        spin_lock(&dev->adev.slock);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
index 60b021e7986473e4187a6326f0ba2f91d62f317b..919ed77b32f2dec7fc6e6b195a9722c6f77f6fbb 100644 (file)
@@ -843,25 +843,34 @@ void cx231xx_release_resources(struct cx231xx *dev)
 
        cx231xx_remove_from_devlist(dev);
 
+       cx231xx_ir_exit(dev);
+
        /* Release I2C buses */
        cx231xx_dev_uninit(dev);
 
-       cx231xx_ir_exit(dev);
+       /* delete v4l2 device */
+       v4l2_device_unregister(&dev->v4l2_dev);
 
        usb_put_dev(dev->udev);
 
        /* Mark device as unused */
-       cx231xx_devused &= ~(1 << dev->devno);
+       clear_bit(dev->devno, &cx231xx_devused);
+
+       kfree(dev->video_mode.alt_max_pkt_size);
+       kfree(dev->vbi_mode.alt_max_pkt_size);
+       kfree(dev->sliced_cc_mode.alt_max_pkt_size);
+       kfree(dev->ts1_mode.alt_max_pkt_size);
+       kfree(dev);
+       dev = NULL;
 }
 
 /*
  * cx231xx_init_dev()
  * allocates and inits the device structs, registers i2c bus and v4l device
  */
-static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
+static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
                            int minor)
 {
-       struct cx231xx *dev = *devhandle;
        int retval = -ENOMEM;
        int errCode;
        unsigned int maxh, maxw;
@@ -1016,7 +1025,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        int i, isoc_pipe = 0;
        char *speed;
        char descr[255] = "";
-       struct usb_interface *lif = NULL;
        struct usb_interface_assoc_descriptor *assoc_desc;
 
        udev = usb_get_dev(interface_to_usbdev(interface));
@@ -1030,21 +1038,21 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
                return -ENODEV;
 
        /* Check to see next free device and mark as used */
-       nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
-       cx231xx_devused |= 1 << nr;
-
-       if (nr >= CX231XX_MAXBOARDS) {
-               cx231xx_err(DRIVER_NAME
-                ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS);
-               cx231xx_devused &= ~(1 << nr);
-               return -ENOMEM;
-       }
+       do {
+               nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+               if (nr >= CX231XX_MAXBOARDS) {
+                       /* No free device slots */
+                       cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+                                       CX231XX_MAXBOARDS);
+                       return -ENOMEM;
+               }
+       } while (test_and_set_bit(nr, &cx231xx_devused));
 
        /* allocate memory for our device state and initialize it */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                cx231xx_err(DRIVER_NAME ": out of memory!\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                return -ENOMEM;
        }
 
@@ -1071,9 +1079,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
        /* init CIR module TBD */
 
-       /* store the current interface */
-       lif = interface;
-
        /*mode_tv: digital=1 or analog=0*/
        dev->mode_tv = 0;
 
@@ -1113,9 +1118,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
             le16_to_cpu(udev->descriptor.idProduct),
             dev->max_iad_interface_count);
 
-       /* store the interface 0 back */
-       lif = udev->actconfig->interface[0];
-
        /* increment interface count */
        dev->interface_count++;
 
@@ -1126,7 +1128,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        if (assoc_desc->bFirstInterface != ifnum) {
                cx231xx_err(DRIVER_NAME ": Not found "
                            "matching IAD interface\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                kfree(dev);
                dev = NULL;
                return -ENODEV;
@@ -1135,7 +1137,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        cx231xx_info("registering interface %d\n", ifnum);
 
        /* save our data pointer in this interface device */
-       usb_set_intfdata(lif, dev);
+       usb_set_intfdata(interface, dev);
 
        /*
         * AV device initialization - only done at the last interface
@@ -1145,19 +1147,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
        if (retval) {
                cx231xx_errdev("v4l2_device_register failed\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                kfree(dev);
                dev = NULL;
                return -EIO;
        }
        /* allocate device struct */
-       retval = cx231xx_init_dev(&dev, udev, nr);
+       retval = cx231xx_init_dev(dev, udev, nr);
        if (retval) {
-               cx231xx_devused &= ~(1 << dev->devno);
+               clear_bit(dev->devno, &cx231xx_devused);
                v4l2_device_unregister(&dev->v4l2_dev);
                kfree(dev);
                dev = NULL;
-               usb_set_intfdata(lif, NULL);
+               usb_set_intfdata(interface, NULL);
 
                return retval;
        }
@@ -1178,7 +1180,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
        if (dev->video_mode.alt_max_pkt_size == NULL) {
                cx231xx_errdev("out of memory!\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                v4l2_device_unregister(&dev->v4l2_dev);
                kfree(dev);
                dev = NULL;
@@ -1212,7 +1214,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
        if (dev->vbi_mode.alt_max_pkt_size == NULL) {
                cx231xx_errdev("out of memory!\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                v4l2_device_unregister(&dev->v4l2_dev);
                kfree(dev);
                dev = NULL;
@@ -1247,7 +1249,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
        if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
                cx231xx_errdev("out of memory!\n");
-               cx231xx_devused &= ~(1 << nr);
+               clear_bit(dev->devno, &cx231xx_devused);
                v4l2_device_unregister(&dev->v4l2_dev);
                kfree(dev);
                dev = NULL;
@@ -1283,7 +1285,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
                if (dev->ts1_mode.alt_max_pkt_size == NULL) {
                        cx231xx_errdev("out of memory!\n");
-                       cx231xx_devused &= ~(1 << nr);
+                       clear_bit(dev->devno, &cx231xx_devused);
                        v4l2_device_unregister(&dev->v4l2_dev);
                        kfree(dev);
                        dev = NULL;
@@ -1334,10 +1336,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
        if (!dev->udev)
                return;
 
-       flush_request_modules(dev);
+       dev->state |= DEV_DISCONNECTED;
 
-       /* delete v4l2 device */
-       v4l2_device_unregister(&dev->v4l2_dev);
+       flush_request_modules(dev);
 
        /* wait until all current v4l2 io is finished then deallocate
           resources */
@@ -1351,31 +1352,24 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
                     "deallocation are deferred on close.\n",
                     video_device_node_name(dev->vdev));
 
-               dev->state |= DEV_MISCONFIGURED;
+               /* Even having users, it is safe to remove the RC i2c driver */
+               cx231xx_ir_exit(dev);
+
                if (dev->USE_ISO)
                        cx231xx_uninit_isoc(dev);
                else
                        cx231xx_uninit_bulk(dev);
-               dev->state |= DEV_DISCONNECTED;
                wake_up_interruptible(&dev->wait_frame);
                wake_up_interruptible(&dev->wait_stream);
        } else {
-               dev->state |= DEV_DISCONNECTED;
-               cx231xx_release_resources(dev);
        }
 
        cx231xx_close_extension(dev);
 
        mutex_unlock(&dev->lock);
 
-       if (!dev->users) {
-               kfree(dev->video_mode.alt_max_pkt_size);
-               kfree(dev->vbi_mode.alt_max_pkt_size);
-               kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-               kfree(dev->ts1_mode.alt_max_pkt_size);
-               kfree(dev);
-               dev = NULL;
-       }
+       if (!dev->users)
+               cx231xx_release_resources(dev);
 }
 
 static struct usb_driver cx231xx_usb_driver = {
index d4457f9488eee6c6e06feb1dd7c7ef727d6b91b8..08dd930f882a60bf566774480f2bb7950f8df4a6 100644 (file)
@@ -166,6 +166,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
        u8 _i2c_nostop = 0;
        u8 _i2c_reserve = 0;
 
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
        /* Get the I2C period, nostop and reserve parameters */
        _i2c_period = i2c_bus->i2c_period;
        _i2c_nostop = i2c_bus->i2c_nostop;
@@ -1071,7 +1074,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
                                 sb_size, cx231xx_isoc_irq_callback, dma_q, 1);
 
                urb->number_of_packets = max_packets;
-               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 
                k = 0;
                for (j = 0; j < max_packets; j++) {
@@ -1182,7 +1185,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
                        return -ENOMEM;
                }
                dev->video_mode.bulk_ctl.urb[i] = urb;
-               urb->transfer_flags = 0;
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 
                dev->video_mode.bulk_ctl.transfer_buffer[i] =
                    usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
index da9a4a0aab7923c96086e7bfc68115911da7e40d..7c4e360ba9bcba325177a881e7d0f9ee052c4fce 100644 (file)
@@ -196,7 +196,7 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
        if (!dev)
                return 0;
 
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+       if (dev->state & DEV_DISCONNECTED)
                return 0;
 
        if (urb->status < 0) {
@@ -228,7 +228,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
        if (!dev)
                return 0;
 
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+       if (dev->state & DEV_DISCONNECTED)
                return 0;
 
        if (urb->status < 0) {
index 45e14cac4622ba03108bd3b4845f6f77a1beab18..96176e9db5a28faa01086e1aca1c364b401efe15 100644 (file)
 static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
                         u32 *ir_raw)
 {
+       int     rc;
        u8      cmd, scancode;
 
        dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
 
                /* poll IR chip */
-       if (1 != i2c_master_recv(ir->c, &cmd, 1))
+       rc = i2c_master_recv(ir->c, &cmd, 1);
+       if (rc < 0)
+               return rc;
+       if (rc != 1)
                return -EIO;
 
        /* it seems that 0xFE indicates that a button is still hold
@@ -102,11 +106,14 @@ int cx231xx_ir_init(struct cx231xx *dev)
        ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
        dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
                ir_i2c_bus, info.addr);
-       i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
+       dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
 
        return 0;
 }
 
 void cx231xx_ir_exit(struct cx231xx *dev)
 {
+       if (dev->ir_i2c_client)
+               i2c_unregister_device(dev->ir_i2c_client);
+       dev->ir_i2c_client = NULL;
 }
index 1c7a4daafecf56f2dc382ebc60b291f197dbbb45..8cdee5f78f131a516918cb9525e0ab23fa31b0f8 100644 (file)
@@ -93,7 +93,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
        if (!dev)
                return 0;
 
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+       if (dev->state & DEV_DISCONNECTED)
                return 0;
 
        if (urb->status < 0) {
@@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
                        return -ENOMEM;
                }
                dev->vbi_mode.bulk_ctl.urb[i] = urb;
-               urb->transfer_flags = 0;
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 
                dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
                    kzalloc(sb_size, GFP_KERNEL);
index 6e81f970dc7d8e35d48975e141c5e75fbfdf878f..829a41b0c9ef5c77edc7095164debac2120f284c 100644 (file)
@@ -337,7 +337,7 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
        if (!dev)
                return 0;
 
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+       if (dev->state & DEV_DISCONNECTED)
                return 0;
 
        if (urb->status < 0) {
@@ -440,7 +440,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
        if (!dev)
                return 0;
 
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+       if (dev->state & DEV_DISCONNECTED)
                return 0;
 
        if (urb->status < 0) {
@@ -1000,12 +1000,6 @@ static int check_dev(struct cx231xx *dev)
                cx231xx_errdev("v4l2 ioctl: device not present\n");
                return -ENODEV;
        }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               cx231xx_errdev("v4l2 ioctl: device is misconfigured; "
-                              "close and open it again\n");
-               return -EIO;
-       }
        return 0;
 }
 
@@ -2347,7 +2341,8 @@ static int cx231xx_v4l2_close(struct file *filp)
                        return 0;
                }
 
-       if (dev->users == 1) {
+       dev->users--;
+       if (!dev->users) {
                videobuf_stop(&fh->vb_vidq);
                videobuf_mmap_free(&fh->vb_vidq);
 
@@ -2374,7 +2369,6 @@ static int cx231xx_v4l2_close(struct file *filp)
                cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
        }
        kfree(fh);
-       dev->users--;
        wake_up_interruptible_nr(&dev->open, 1);
        return 0;
 }
index 2000bc64c49784af168855f9dfab150b078a6d48..e17447554a0d6eed2de8deb94360019e20114cea 100644 (file)
@@ -377,7 +377,6 @@ struct cx231xx_board {
 enum cx231xx_dev_state {
        DEV_INITIALIZED = 0x01,
        DEV_DISCONNECTED = 0x02,
-       DEV_MISCONFIGURED = 0x04,
 };
 
 enum AFE_MODE {
@@ -621,6 +620,7 @@ struct cx231xx {
 
        /* For I2C IR support */
        struct IR_i2c_init_data    init_data;
+       struct i2c_client          *ir_i2c_client;
 
        unsigned int stream_on:1;       /* Locks streams */
        unsigned int vbi_stream_on:1;   /* Locks streams for VBI */
index 67c4a59bd8825800cda0bd1e657c92673ab4c944..f5c79e53e5a145bce2fc8a0f898ca7482d2ab0e6 100644 (file)
@@ -900,6 +900,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
        int i, retval = 0;
        u32 value = 0;
        u32 gpio_output = 0;
+       u32 gpio_value;
        u32 checksum = 0;
        u32 *dataptr;
 
@@ -907,7 +908,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
 
        /* Save GPIO settings before reset of APU */
        retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
-       retval |= mc417_memory_read(dev, 0x900C, &value);
+       retval |= mc417_memory_read(dev, 0x900C, &gpio_value);
 
        retval  = mc417_register_write(dev,
                IVTV_REG_VPU, 0xFFFFFFED);
@@ -991,11 +992,18 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
 
        /* F/W power up disturbs the GPIOs, restore state */
        retval |= mc417_register_write(dev, 0x9020, gpio_output);
-       retval |= mc417_register_write(dev, 0x900C, value);
+       retval |= mc417_register_write(dev, 0x900C, gpio_value);
 
        retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
        retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
 
+       /* Hardcoded GPIO's here */
+       retval |= mc417_register_write(dev, 0x9020, 0x4000);
+       retval |= mc417_register_write(dev, 0x900C, 0x4000);
+
+       mc417_register_read(dev, 0x9020, &gpio_output);
+       mc417_register_read(dev, 0x900C, &gpio_value);
+
        if (retval < 0)
                printk(KERN_ERR "%s: Error with mc417_register_write\n",
                        __func__);
@@ -1015,6 +1023,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev)
 {
        dprintk(1, "%s()\n", __func__);
 
+       /* Dynamically change the height based on video standard */
+       if (dev->encodernorm.id & V4L2_STD_525_60)
+               dev->ts1.height = 480;
+       else
+               dev->ts1.height = 576;
+
        /* assign frame size */
        cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
                                dev->ts1.height, dev->ts1.width);
@@ -1030,7 +1044,7 @@ static void cx23885_codec_settings(struct cx23885_dev *dev)
        cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
 }
 
-static int cx23885_initialize_codec(struct cx23885_dev *dev)
+static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
 {
        int version;
        int retval;
@@ -1112,9 +1126,11 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev)
        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);
+       if (startencoder) {
+               cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+                       CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+               msleep(10);
+       }
 
        return 0;
 }
@@ -1196,6 +1212,16 @@ static int cx23885_querymenu(struct cx23885_dev *dev,
                cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
 }
 
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       call_all(dev, core, g_std, id);
+
+       return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
        struct cx23885_fh  *fh  = file->private_data;
@@ -1208,55 +1234,31 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
        if (i == ARRAY_SIZE(cx23885_tvnorms))
                return -EINVAL;
        dev->encodernorm = cx23885_tvnorms[i];
+
+       /* Have the drier core notify the subdevices */
+       mutex_lock(&dev->lock);
+       cx23885_set_tvnorm(dev, *id);
+       mutex_unlock(&dev->lock);
+
        return 0;
 }
 
 static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
+       struct v4l2_input *i)
 {
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-       struct cx23885_input *input;
-       int n;
-
-       if (i->index >= 4)
-               return -EINVAL;
-
-       input = &cx23885_boards[dev->board].input[i->index];
-
-       if (input->type == 0)
-               return -EINVAL;
-
-       /* 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;
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+       return cx23885_enum_input(dev, i);
 }
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       *i = dev->input;
-       return 0;
+       return cx23885_get_input(file, priv, i);
 }
 
 static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
-       if (i >= 4)
-               return -EINVAL;
-
-       return 0;
+       return cx23885_set_input(file, priv, i);
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
@@ -1309,43 +1311,25 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
+       struct v4l2_frequency *f)
 {
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-               CX23885_END_NOW, CX23885_MPEG_CAPTURE,
-               CX23885_RAW_BITS_NONE);
-
-       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;
-
-       call_all(dev, tuner, s_frequency, f);
+       return cx23885_set_frequency(file, priv, f);
+}
 
-       cx23885_initialize_codec(dev);
+static int vidioc_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-       return 0;
+       return cx23885_get_control(dev, ctl);
 }
 
 static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctl)
+       struct v4l2_control *ctl)
 {
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-       /* Update the A/V core */
-       call_all(dev, core, s_ctrl, ctl);
-       return 0;
+       return cx23885_set_control(dev, ctl);
 }
 
 static int vidioc_querycap(struct file *file, void  *priv,
@@ -1636,7 +1620,7 @@ static ssize_t mpeg_read(struct file *file, char __user *data,
        /* 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)
+                       if (cx23885_initialize_codec(dev, 1) < 0)
                                return -EINVAL;
                }
        }
@@ -1677,6 +1661,8 @@ static struct v4l2_file_operations mpeg_fops = {
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+       .vidioc_querystd         = vidioc_g_std,
+       .vidioc_g_std            = vidioc_g_std,
        .vidioc_s_std            = vidioc_s_std,
        .vidioc_enum_input       = vidioc_enum_input,
        .vidioc_g_input          = vidioc_g_input,
@@ -1686,6 +1672,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_g_frequency      = vidioc_g_frequency,
        .vidioc_s_frequency      = vidioc_s_frequency,
        .vidioc_s_ctrl           = vidioc_s_ctrl,
+       .vidioc_g_ctrl           = vidioc_g_ctrl,
        .vidioc_querycap         = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
@@ -1746,8 +1733,8 @@ static struct video_device *cx23885_video_dev_alloc(
        if (NULL == vfd)
                return NULL;
        *vfd = *template;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
-               type, cx23885_boards[tsport->dev->board].name);
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+               cx23885_boards[tsport->dev->board].name, type);
        vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        return vfd;
@@ -1791,5 +1778,11 @@ int cx23885_417_register(struct cx23885_dev *dev)
        printk(KERN_INFO "%s: registered device %s [mpeg]\n",
               dev->name, video_device_node_name(dev->v4l_device));
 
+       /* ST: Configure the encoder paramaters, but don't begin
+        * encoding, this resolves an issue where the first time the
+        * encoder is started video can be choppy.
+        */
+       cx23885_initialize_codec(dev, 0);
+
        return 0;
 }
index c3cf08945e4cf853f2acb959b64ab7eaac8291f7..3c01be999e353817718ab342c27943fc1a52d78f 100644 (file)
@@ -335,8 +335,33 @@ struct cx23885_board cx23885_boards[] = {
        },
        [CX23885_BOARD_HAUPPAUGE_HVR1850] = {
                .name           = "Hauppauge WinTV-HVR1850",
+               .porta          = CX23885_ANALOG_VIDEO,
                .portb          = CX23885_MPEG_ENCODER,
                .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
        },
        [CX23885_BOARD_COMPRO_VIDEOMATE_E800] = {
                .name           = "Compro VideoMate E800",
@@ -438,6 +463,41 @@ struct cx23885_board cx23885_boards[] = {
                        .gpio0  = 0,
                } },
        },
+       [CX23885_BOARD_MYGICA_X8507] = {
+               .name           = "Mygica X8507",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_bus      = 1,
+               .porta          = CX23885_ANALOG_VIDEO,
+               .input          = {
+                       {
+                               .type   = CX23885_VMUX_TELEVISION,
+                               .vmux   = CX25840_COMPOSITE2,
+                               .amux   = CX25840_AUDIO8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPOSITE1,
+                               .vmux   = CX25840_COMPOSITE8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_SVIDEO,
+                               .vmux   = CX25840_SVIDEO_LUMA3 |
+                                               CX25840_SVIDEO_CHROMA4,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPONENT,
+                               .vmux   = CX25840_COMPONENT_ON |
+                                       CX25840_VIN1_CH1 |
+                                       CX25840_VIN6_CH2 |
+                                       CX25840_VIN7_CH3,
+                       },
+               },
+       },
+       [CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = {
+               .name           = "TerraTec Cinergy T PCIe Dual",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       }
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -637,6 +697,14 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x1b55,
                .subdevice = 0xe2e4,
                .card      = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8502,
+               .card      = CX23885_BOARD_MYGICA_X8507,
+       }, {
+               .subvendor = 0x153b,
+               .subdevice = 0x117e,
+               .card      = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1068,6 +1136,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                break;
        case CX23885_BOARD_MYGICA_X8506:
        case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+       case CX23885_BOARD_MYGICA_X8507:
                /* GPIO-0 (0)Analog / (1)Digital TV */
                /* GPIO-1 reset XC5000 */
                /* GPIO-2 reset LGS8GL5 / LGS8G75 */
@@ -1367,6 +1436,7 @@ 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_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
                /* Defaults for VID B - Analog encoder */
                /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
@@ -1377,6 +1447,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                /* APB_TSVALERR_POL (active low)*/
                ts1->vld_misc_val    = 0x2000;
                ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+               cx_write(0x130184, 0xc);
 
                /* Defaults for VID C */
                ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
@@ -1396,6 +1467,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                break;
        case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
        case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
                ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
                ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1431,7 +1503,6 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
        case CX23885_BOARD_HAUPPAUGE_HVR1210:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
        case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
@@ -1468,6 +1539,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_MPX885:
+       case CX23885_BOARD_MYGICA_X8507:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
                dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
                                &dev->i2c_bus[2].i2c_adap,
                                "cx25840", 0x88 >> 1, NULL);
index 40e68b22015eea4c54ce28babecd2701feb03d1c..6ad227029a0f2b497f9b7853891fb107b85c192e 100644 (file)
@@ -206,12 +206,12 @@ static struct sram_channel cx23887_sram_channels[] = {
                .cnt2_reg       = DMA1_CNT2,
        },
        [SRAM_CH02] = {
-               .name           = "ch2",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
+               .name           = "VID A (VBI)",
+               .cmds_start     = 0x10050,
+               .ctrl_start     = 0x105F0,
+               .cdt            = 0x10810,
+               .fifo_start     = 0x3000,
+               .fifo_size      = 0x1000,
                .ptr1_reg       = DMA2_PTR1,
                .ptr2_reg       = DMA2_PTR2,
                .cnt1_reg       = DMA2_CNT1,
@@ -266,12 +266,12 @@ static struct sram_channel cx23887_sram_channels[] = {
                .cnt2_reg       = DMA5_CNT2,
        },
        [SRAM_CH07] = {
-               .name           = "ch7",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
+               .name           = "TV Audio",
+               .cmds_start     = 0x10190,
+               .ctrl_start     = 0x106B0,
+               .cdt            = 0x10930,
+               .fifo_start     = 0x7000,
+               .fifo_size      = 0x1000,
                .ptr1_reg       = DMA6_PTR1,
                .ptr2_reg       = DMA6_PTR2,
                .cnt1_reg       = DMA6_CNT1,
index bcb45be44bb279a2085bd20f1491a58eee962d6e..af8a225763d3dbfc3a41068855625a83bf13d4cd 100644 (file)
@@ -61,6 +61,8 @@
 #include "cx23885-f300.h"
 #include "altera-ci.h"
 #include "stv0367.h"
+#include "drxk.h"
+#include "mt2063.h"
 
 static unsigned int debug;
 
@@ -111,6 +113,8 @@ static void dvb_buf_release(struct videobuf_queue *q,
        cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
 }
 
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
+
 static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
 {
        struct videobuf_dvb_frontends *f;
@@ -125,6 +129,12 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
 
        if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
                fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+
+       /*
+        * FIXME: Improve this path to avoid calling the
+        * cx23885_dvb_set_frontend() every time it passes here.
+        */
+       cx23885_dvb_set_frontend(fe->dvb.frontend);
 }
 
 static struct videobuf_queue_ops dvb_qops = {
@@ -479,15 +489,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
        .if_khz = 5380,
 };
 
-static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
-                                   struct dvb_frontend_parameters *param)
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct cx23885_tsport *port = fe->dvb->priv;
        struct cx23885_dev *dev = port->dev;
 
        switch (dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1275:
-               switch (param->u.vsb.modulation) {
+               switch (p->modulation) {
                case VSB_8:
                        cx23885_gpio_clear(dev, GPIO_5);
                        break;
@@ -507,31 +517,6 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
        return 0;
 }
 
-static int cx23885_dvb_fe_ioctl_override(struct dvb_frontend *fe,
-                                        unsigned int cmd, void *parg,
-                                        unsigned int stage)
-{
-       int err = 0;
-
-       switch (stage) {
-       case DVB_FE_IOCTL_PRE:
-
-               switch (cmd) {
-               case FE_SET_FRONTEND:
-                       err = cx23885_dvb_set_frontend(fe,
-                               (struct dvb_frontend_parameters *) parg);
-                       break;
-               }
-               break;
-
-       case DVB_FE_IOCTL_POST:
-               /* no post-ioctl handling required */
-               break;
-       }
-       return err;
-};
-
-
 static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
        .prod = LGS8GXX_PROD_LGS8G75,
        .demod_address = 0x19,
@@ -617,6 +602,24 @@ static struct xc5000_config netup_xc5000_config[] = {
        },
 };
 
+static struct drxk_config terratec_drxk_config[] = {
+       {
+               .adr = 0x29,
+               .no_i2c_bridge = 1,
+       }, {
+               .adr = 0x2a,
+               .no_i2c_bridge = 1,
+       },
+};
+
+static struct mt2063_config terratec_mt2063_config[] = {
+       {
+               .tuner_address = 0x60,
+       }, {
+               .tuner_address = 0x67,
+       },
+};
+
 int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
        struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1043,6 +1046,20 @@ static int dvb_register(struct cx23885_tsport *port)
                }
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                       &hcw_s5h1411_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                               0x60, &dev->i2c_bus[0].i2c_adap,
+                               &hauppauge_tda18271_config);
+
+               tda18271_attach(&dev->ts1.analog_fe,
+                       0x60, &dev->i2c_bus[1].i2c_adap,
+                       &hauppauge_tda18271_config);
+
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
                i2c_bus = &dev->i2c_bus[0];
                fe0->dvb.frontend = dvb_attach(s5h1411_attach,
@@ -1118,6 +1135,39 @@ static int dvb_register(struct cx23885_tsport *port)
                                goto frontend_detach;
                }
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               i2c_bus = &dev->i2c_bus[0];
+               i2c_bus2 = &dev->i2c_bus[1];
+
+               switch (port->nr) {
+               /* port b */
+               case 1:
+                       fe0->dvb.frontend = dvb_attach(drxk_attach,
+                                       &terratec_drxk_config[0],
+                                       &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (!dvb_attach(mt2063_attach,
+                                               fe0->dvb.frontend,
+                                               &terratec_mt2063_config[0],
+                                               &i2c_bus2->i2c_adap))
+                                       goto frontend_detach;
+                       }
+                       break;
+               /* port c */
+               case 2:
+                       fe0->dvb.frontend = dvb_attach(drxk_attach,
+                                       &terratec_drxk_config[1],
+                                       &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (!dvb_attach(mt2063_attach,
+                                               fe0->dvb.frontend,
+                                               &terratec_mt2063_config[1],
+                                               &i2c_bus2->i2c_adap))
+                                       goto frontend_detach;
+                       }
+                       break;
+               }
+               break;
        default:
                printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
                        " isn't supported yet\n",
@@ -1151,7 +1201,7 @@ static int dvb_register(struct cx23885_tsport *port)
        /* register everything */
        ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
                                        &dev->pci->dev, adapter_nr, mfe_shared,
-                                       cx23885_dvb_fe_ioctl_override);
+                                       NULL);
        if (ret)
                goto frontend_detach;
 
index 0ff7a9e98f3e637c6a9ef6d258c08e80de2e8c6c..be1e21d8295c8b382c0289d3265d7038abb2f73a 100644 (file)
@@ -309,7 +309,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
        }
 }
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int cx23885_i2c_register(struct cx23885_i2c *bus)
 {
        struct cx23885_dev *dev = bus->dev;
index e730b92630161b58b5d4c8278e48d394910b95b3..4bbf9bb97bde984e23c0665fda59a72bc7dbd80a 100644 (file)
@@ -253,9 +253,9 @@ static struct cx23885_ctrl cx23885_ctls[] = {
                        .id            = V4L2_CID_AUDIO_VOLUME,
                        .name          = "Volume",
                        .minimum       = 0,
-                       .maximum       = 0x3f,
-                       .step          = 1,
-                       .default_value = 0x3f,
+                       .maximum       = 65535,
+                       .step          = 65535 / 100,
+                       .default_value = 65535,
                        .type          = V4L2_CTRL_TYPE_INTEGER,
                },
                .reg                   = PATH1_VOL_CTL,
@@ -316,7 +316,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
                        __func__, bc);
 }
 
-static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 {
        dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
                __func__,
@@ -344,8 +344,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
        *vfd = *template;
        vfd->v4l2_dev = &dev->v4l2_dev;
        vfd->release = video_device_release;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
-                dev->name, type, cx23885_boards[dev->board].name);
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+                cx23885_boards[dev->board].name, type);
        video_set_drvdata(vfd, dev);
        return vfd;
 }
@@ -492,7 +492,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
        dev->input = input;
 
        if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
-               dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) {
+               dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 ||
+               dev->board == CX23885_BOARD_MYGICA_X8507) {
                /* Select Analog TV */
                if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
                        cx23885_gpio_clear(dev, GPIO_0);
@@ -503,7 +504,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
                        INPUT(input)->vmux, 0, 0);
 
        if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
-               (dev->board == CX23885_BOARD_MPX885)) {
+               (dev->board == CX23885_BOARD_MPX885) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
                /* Configure audio routing */
                v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
                        INPUT(input)->amux, 0, 0);
@@ -649,6 +651,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
        int rc, init_buffer = 0;
        u32 line0_offset, line1_offset;
        struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       int field_tff;
 
        BUG_ON(NULL == fh->fmt);
        if (fh->width  < 48 || fh->width  > norm_maxw(dev->tvnorm) ||
@@ -690,15 +693,25 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                                         buf->bpl, 0, buf->vb.height);
                        break;
                case V4L2_FIELD_INTERLACED:
-                       if (dev->tvnorm & V4L2_STD_NTSC) {
+                       if (dev->tvnorm & V4L2_STD_NTSC)
+                               /* NTSC or  */
+                               field_tff = 1;
+                       else
+                               field_tff = 0;
+
+                       if (cx23885_boards[dev->board].force_bff)
+                               /* PAL / SECAM OR 888 in NTSC MODE */
+                               field_tff = 0;
+
+                       if (field_tff) {
                                /* cx25840 transmits NTSC bottom field first */
-                               dprintk(1, "%s() Creating NTSC risc\n",
+                               dprintk(1, "%s() Creating TFF/NTSC risc\n",
                                        __func__);
                                line0_offset = buf->bpl;
                                line1_offset = 0;
                        } else {
                                /* All other formats are top field first */
-                               dprintk(1, "%s() Creating PAL/SECAM risc\n",
+                               dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n",
                                        __func__);
                                line0_offset = 0;
                                line1_offset = buf->bpl;
@@ -981,6 +994,8 @@ static int video_release(struct file *file)
        }
 
        videobuf_mmap_free(&fh->vidq);
+       videobuf_mmap_free(&fh->vbiq);
+
        file->private_data = NULL;
        kfree(fh);
 
@@ -1002,7 +1017,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
 /* ------------------------------------------------------------------ */
 /* VIDEO CTRL IOCTLS                                                  */
 
-static int cx23885_get_control(struct cx23885_dev *dev,
+int cx23885_get_control(struct cx23885_dev *dev,
        struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
@@ -1010,7 +1025,7 @@ static int cx23885_get_control(struct cx23885_dev *dev,
        return 0;
 }
 
-static int cx23885_set_control(struct cx23885_dev *dev,
+int cx23885_set_control(struct cx23885_dev *dev,
        struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
@@ -1229,6 +1244,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
        return 0;
 }
 
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+
+       call_all(dev, core, g_std, id);
+
+       return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -1241,7 +1266,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
        return 0;
 }
 
-static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
 {
        static const char *iname[] = {
                [CX23885_VMUX_COMPOSITE1] = "Composite1",
@@ -1278,6 +1303,15 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
        if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
                i->audioset = 0x3;
 
+       if (dev->input == n) {
+               /* enum'd input matches our configured input.
+                * Ask the video decoder to process the call
+                * and give it an oppertunity to update the
+                * status field.
+                */
+               call_all(dev, video, g_input_status, &i->status);
+       }
+
        return 0;
 }
 
@@ -1289,7 +1323,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
        return cx23885_enum_input(dev, i);
 }
 
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
@@ -1298,7 +1332,12 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
        return 0;
 }
 
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       return cx23885_get_input(file, priv, i);
+}
+
+int cx23885_set_input(struct file *file, void *priv, unsigned int i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
@@ -1322,6 +1361,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        return 0;
 }
 
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       return cx23885_set_input(file, priv, i);
+}
+
 static int vidioc_log_status(struct file *file, void *priv)
 {
        struct cx23885_fh  *fh  = priv;
@@ -1329,11 +1373,11 @@ static int vidioc_log_status(struct file *file, void *priv)
 
        printk(KERN_INFO
                "%s/0: ============  START LOG STATUS  ============\n",
-              dev->name);
+               dev->name);
        call_all(dev, core, log_status);
        printk(KERN_INFO
                "%s/0: =============  END LOG STATUS  =============\n",
-              dev->name);
+               dev->name);
        return 0;
 }
 
@@ -1471,6 +1515,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 
 static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
 {
+       struct v4l2_control ctrl;
+
        if (unlikely(UNSET == dev->tuner_type))
                return -EINVAL;
        if (unlikely(f->tuner != 0))
@@ -1479,29 +1525,102 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
        mutex_lock(&dev->lock);
        dev->freq = f->frequency;
 
+       /* I need to mute audio here */
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = 1;
+       cx23885_set_control(dev, &ctrl);
+
        call_all(dev, tuner, s_frequency, f);
 
        /* When changing channels it is required to reset TVAUDIO */
-       msleep(10);
+       msleep(100);
+
+       /* I need to unmute audio here */
+       ctrl.value = 0;
+       cx23885_set_control(dev, &ctrl);
 
        mutex_unlock(&dev->lock);
 
        return 0;
 }
 
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
+static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
+       struct v4l2_frequency *f)
+{
+       struct v4l2_control ctrl;
+       struct videobuf_dvb_frontend *vfe;
+       struct dvb_frontend *fe;
+       int err = 0;
+
+       struct analog_parameters params = {
+               .mode      = V4L2_TUNER_ANALOG_TV,
+               .audmode   = V4L2_TUNER_MODE_STEREO,
+               .std       = dev->tvnorm,
+               .frequency = f->frequency
+       };
+
+       mutex_lock(&dev->lock);
+       dev->freq = f->frequency;
+
+       /* I need to mute audio here */
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = 1;
+       cx23885_set_control(dev, &ctrl);
+
+       /* If HVR1850 */
+       dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__,
+               params.frequency, f->tuner, params.std);
+
+       vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
+       if (!vfe)
+               err = -EINVAL;
+
+       fe = vfe->dvb.frontend;
+
+       if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)
+               fe = &dev->ts1.analog_fe;
+
+       if (fe && fe->ops.tuner_ops.set_analog_params) {
+               call_all(dev, core, s_std, dev->tvnorm);
+               fe->ops.tuner_ops.set_analog_params(fe, &params);
+       }
+       else
+               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep(100);
+
+       /* I need to unmute audio here */
+       ctrl.value = 0;
+       cx23885_set_control(dev, &ctrl);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+int cx23885_set_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
 {
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev = fh->dev;
+       int ret;
 
-       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
-               return -EINVAL;
-       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
-               return -EINVAL;
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+               ret = cx23885_set_freq_via_ops(dev, f);
+               break;
+       default:
+               ret = cx23885_set_freq(dev, f);
+       }
 
-       return
-               cx23885_set_freq(dev, f);
+       return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       return cx23885_set_frequency(file, priv, f);
 }
 
 /* ----------------------------------------------------------- */
@@ -1613,6 +1732,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_qbuf          = vidioc_qbuf,
        .vidioc_dqbuf         = vidioc_dqbuf,
        .vidioc_s_std         = vidioc_s_std,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_querystd      = vidioc_g_std,
        .vidioc_enum_input    = vidioc_enum_input,
        .vidioc_g_input       = vidioc_g_input,
        .vidioc_s_input       = vidioc_s_input,
index b49036fe3ffdc52fcea1bf946a423594e4a5f242..f020f0568df4a8c8c15d098c1c4d6ad9f39367f5 100644 (file)
@@ -87,6 +87,8 @@
 #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
 #define CX23885_BOARD_MPX885                   32
+#define CX23885_BOARD_MYGICA_X8507             33
+#define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -226,6 +228,8 @@ struct cx23885_board {
        u32                     clk_freq;
        struct cx23885_input    input[MAX_CX23885_INPUT];
        int                     ci_type; /* for NetUP */
+       /* Force bottom field first during DMA (888 workaround) */
+       u32                     force_bff;
 };
 
 struct cx23885_subid {
@@ -310,6 +314,9 @@ struct cx23885_tsport {
        u32                        num_frontends;
        void                (*gate_ctrl)(struct cx23885_tsport *port, int open);
        void                       *port_priv;
+
+       /* Workaround for a temp dvb_frontend that the tuner can attached to */
+       struct dvb_frontend analog_fe;
 };
 
 struct cx23885_kernel_ir {
@@ -574,6 +581,13 @@ extern void cx23885_video_unregister(struct cx23885_dev *dev);
 extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
 extern void cx23885_video_wakeup(struct cx23885_dev *dev,
        struct cx23885_dmaqueue *q, u32 count);
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
+int cx23885_set_input(struct file *file, void *priv, unsigned int i);
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
+int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
 
 /* ----------------------------------------------------------- */
 /* cx23885-vbi.c                                               */
index 58be4f3bb3cb40e4ca3723b64afa84ba8294ee9a..03cfac476b032b547297c2a38e1d97d764c6a486 100644 (file)
@@ -176,8 +176,7 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
 
        /* Set the input mode to 16-bit */
        tmp = cx_read(AUD_A_CFG);
-       cx_write(AUD_A_CFG,
-                tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+       cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
                 FLD_AUD_CLK_ENABLE);
 
        /*
@@ -188,9 +187,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
        */
 
        /* Enables corresponding bits at AUD_INT_STAT */
-       cx_write(AUD_A_INT_MSK,
-                FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC |
-                FLD_AUD_DST_OPC_ERR);
+       cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF |
+                FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR);
 
        /* Clean any pending interrupt bits already set */
        cx_write(AUD_A_INT_STAT, ~0);
@@ -200,8 +198,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
 
        /* Turn on audio downstream fifo and risc enable 0x101 */
        tmp = cx_read(AUD_INT_DMA_CTL);
-       cx_set(AUD_INT_DMA_CTL,
-              tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+       cx_set(AUD_INT_DMA_CTL, tmp |
+              (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
 
        mdelay(100);
        return 0;
@@ -220,9 +218,8 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
 
        /* disable irqs */
        cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
-       cx_clear(AUD_A_INT_MSK,
-                AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 |
-                AUD_INT_DN_RISCI1);
+       cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
 
        return 0;
 }
@@ -234,15 +231,15 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
  */
 static char *cx25821_aud_irqs[32] = {
        "dn_risci1", "up_risci1", "rds_dn_risc1",       /* 0-2 */
-       NULL,                   /* reserved */
+       NULL,                                           /* reserved */
        "dn_risci2", "up_risci2", "rds_dn_risc2",       /* 4-6 */
-       NULL,                   /* reserved */
-       "dnf_of", "upf_uf", "rds_dnf_uf",       /* 8-10 */
-       NULL,                   /* reserved */
-       "dn_sync", "up_sync", "rds_dn_sync",    /* 12-14 */
-       NULL,                   /* reserved */
-       "opc_err", "par_err", "rip_err",        /* 16-18 */
-       "pci_abort", "ber_irq", "mchg_irq"      /* 19-21 */
+       NULL,                                           /* reserved */
+       "dnf_of", "upf_uf", "rds_dnf_uf",               /* 8-10 */
+       NULL,                                           /* reserved */
+       "dn_sync", "up_sync", "rds_dn_sync",            /* 12-14 */
+       NULL,                                           /* reserved */
+       "opc_err", "par_err", "rip_err",                /* 16-18 */
+       "pci_abort", "ber_irq", "mchg_irq"              /* 19-21 */
 };
 
 /*
@@ -258,10 +255,8 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
 
        cx_write(AUD_A_INT_STAT, status);
        if (debug > 1 || (status & mask & ~0xff))
-               cx25821_print_irqbits(dev->name, "irq aud",
-                                     cx25821_aud_irqs,
-                                     ARRAY_SIZE(cx25821_aud_irqs), status,
-                                     mask);
+               cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs,
+                               ARRAY_SIZE(cx25821_aud_irqs), status, mask);
 
        /* risc op code error */
        if (status & AUD_INT_OPC_ERR) {
@@ -270,8 +265,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
                cx_clear(AUD_INT_DMA_CTL,
                         FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
                cx25821_sram_channel_dump_audio(dev,
-                                               &cx25821_sram_channels
-                                               [AUDIO_SRAM_CHANNEL]);
+                               &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
        }
        if (status & AUD_INT_DN_SYNC) {
                pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
@@ -317,8 +311,9 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id)
                                cx25821_aud_irq(chip, audint_status,
                                                audint_mask);
                                break;
-                       } else
+                       } else {
                                goto out;
+                       }
                }
 
                handled = 1;
@@ -361,9 +356,8 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip)
  */
 #define DEFAULT_FIFO_SIZE      384
 static struct snd_pcm_hardware snd_cx25821_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP |
-           SNDRV_PCM_INFO_INTERLEAVED |
-           SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+       .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_48000,
@@ -396,8 +390,8 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
                return -ENODEV;
        }
 
-       err =
-           snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+       err = snd_pcm_hw_constraint_pow2(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_PERIODS);
        if (err < 0)
                goto _error;
 
@@ -468,8 +462,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
        dma = &buf->dma;
        videobuf_dma_init(dma);
        ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
-                                      (PAGE_ALIGN(chip->dma_size) >>
-                                       PAGE_SHIFT));
+                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
        if (ret < 0)
                goto error;
 
@@ -477,10 +470,8 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                goto error;
 
-       ret =
-           cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
-                                         chip->period_size, chip->num_periods,
-                                         1);
+       ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+                       chip->period_size, chip->num_periods, 1);
        if (ret < 0) {
                pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
                goto error;
@@ -686,7 +677,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
        }
 
        err = snd_card_create(index[devno], id[devno], THIS_MODULE,
-                        sizeof(struct cx25821_audio_dev), &card);
+                       sizeof(struct cx25821_audio_dev), &card);
        if (err < 0) {
                pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
                        __func__);
@@ -711,8 +702,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
                          IRQF_SHARED, chip->dev->name, chip);
 
        if (err < 0) {
-               pr_err("ERROR %s: can't get IRQ %d for ALSA\n",
-                      chip->dev->name, dev->pci->irq);
+               pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
+                       dev->pci->irq);
                goto error;
        }
 
@@ -730,8 +721,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
                chip->iobase, chip->irq);
        strcpy(card->mixername, "CX25821");
 
-       pr_info("%s/%i: ALSA support for cx25821 boards\n",
-               card->driver, devno);
+       pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
+               devno);
 
        err = snd_card_register(card);
        if (err < 0) {
index c20d6dece154ee66066c1456b1284f314b89a1ee..20c7ca3351a8df7399d05af0a850867e32140662 100644 (file)
@@ -107,7 +107,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
 {
        unsigned int line;
        struct sram_channel *sram_ch =
-          dev->channels[dev->_audio_upstream_channel].sram_channels;
+               dev->channels[dev->_audio_upstream_channel].sram_channels;
        int offset = 0;
 
        /* scan lines */
@@ -175,10 +175,8 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
                }
 
                rp = cx25821_risc_field_upstream_audio(dev, rp,
-                                                      dev->
-                                                      _audiodata_buf_phys_addr
-                                                      + databuf_offset, bpl,
-                                                      fifo_enable);
+                               dev->_audiodata_buf_phys_addr + databuf_offset,
+                               bpl, fifo_enable);
 
                if (USE_RISC_NOOP_AUDIO) {
                        for (i = 0; i < NUM_NO_OPS; i++)
@@ -193,7 +191,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
 
                /* Recalculate virtual address based on frame index */
                rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
-                   (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+                       (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
        }
 
        return 0;
@@ -218,7 +216,7 @@ void cx25821_free_memory_audio(struct cx25821_dev *dev)
 void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
 {
        struct sram_channel *sram_ch =
-          dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+               dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
        u32 tmp = 0;
 
        if (!dev->_audio_is_running) {
@@ -286,14 +284,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
        } else {
                if (!(myfile->f_op)) {
                        pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
+                               __func__);
                        filp_close(myfile, NULL);
                        return -EIO;
                }
 
                if (!myfile->f_op->read) {
                        pr_err("%s(): File has no READ operations registered!\n",
-                              __func__);
+                               __func__);
                        filp_close(myfile, NULL);
                        return -EIO;
                }
@@ -305,14 +303,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
                for (i = 0; i < dev->_audio_lines_count; i++) {
                        pos = file_offset;
 
-                       vfs_read_retval =
-                           vfs_read(myfile, mybuf, line_size, &pos);
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                                                       &pos);
 
                        if (vfs_read_retval > 0 && vfs_read_retval == line_size
                            && dev->_audiodata_buf_virt_addr != NULL) {
                                memcpy((void *)(dev->_audiodata_buf_virt_addr +
                                                frame_offset / 4), mybuf,
-                                      vfs_read_retval);
+                                       vfs_read_retval);
                        }
 
                        file_offset += vfs_read_retval;
@@ -328,8 +326,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
                if (i > 0)
                        dev->_audioframe_count++;
 
-               dev->_audiofile_status =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_audiofile_status = (vfs_read_retval == line_size) ?
+                                               IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                filp_close(myfile, NULL);
@@ -340,12 +338,12 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
 
 static void cx25821_audioups_handler(struct work_struct *work)
 {
-       struct cx25821_dev *dev =
-           container_of(work, struct cx25821_dev, _audio_work_entry);
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _audio_work_entry);
 
        if (!dev) {
                pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
-                      __func__);
+                       __func__);
                return;
        }
 
@@ -370,19 +368,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
        if (IS_ERR(myfile)) {
                const int open_errno = -PTR_ERR(myfile);
                pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_audiofilename, open_errno);
+                       __func__, dev->_audiofilename, open_errno);
                return PTR_ERR(myfile);
        } else {
                if (!(myfile->f_op)) {
                        pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
+                               __func__);
                        filp_close(myfile, NULL);
                        return -EIO;
                }
 
                if (!myfile->f_op->read) {
                        pr_err("%s(): File has no READ operations registered!\n",
-                              __func__);
+                               __func__);
                        filp_close(myfile, NULL);
                        return -EIO;
                }
@@ -395,12 +393,12 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
                        for (i = 0; i < dev->_audio_lines_count; i++) {
                                pos = offset;
 
-                               vfs_read_retval =
-                                   vfs_read(myfile, mybuf, line_size, &pos);
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
 
-                               if (vfs_read_retval > 0
-                                   && vfs_read_retval == line_size
-                                   && dev->_audiodata_buf_virt_addr != NULL) {
+                               if (vfs_read_retval > 0 &&
+                                   vfs_read_retval == line_size &&
+                                   dev->_audiodata_buf_virt_addr != NULL) {
                                        memcpy((void *)(dev->
                                                        _audiodata_buf_virt_addr
                                                        + offset / 4), mybuf,
@@ -423,8 +421,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
                                break;
                }
 
-               dev->_audiofile_status =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_audiofile_status = (vfs_read_retval == line_size) ?
+                                               IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                myfile->f_pos = 0;
@@ -444,9 +442,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
 
        cx25821_free_memory_audio(dev);
 
-       dev->_risc_virt_addr =
-           pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size,
-                                &dma_addr);
+       dev->_risc_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->audio_upstream_riscbuf_size, &dma_addr);
        dev->_risc_virt_start_addr = dev->_risc_virt_addr;
        dev->_risc_phys_start_addr = dma_addr;
        dev->_risc_phys_addr = dma_addr;
@@ -454,22 +451,21 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
 
        if (!dev->_risc_virt_addr) {
                printk(KERN_DEBUG
-                      pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
                return -ENOMEM;
        }
        /* Clear out memory at address */
        memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
 
        /* For Audio Data buffer allocation */
-       dev->_audiodata_buf_virt_addr =
-           pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size,
-                                &data_dma_addr);
+       dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->audio_upstream_databuf_size, &data_dma_addr);
        dev->_audiodata_buf_phys_addr = data_dma_addr;
        dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
 
        if (!dev->_audiodata_buf_virt_addr) {
                printk(KERN_DEBUG
-                      pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
                return -ENOMEM;
        }
        /* Clear out memory at address */
@@ -480,12 +476,11 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
                return ret;
 
        /* Creating RISC programs */
-       ret =
-           cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
-                                              dev->_audio_lines_count);
+       ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+                                               dev->_audio_lines_count);
        if (ret < 0) {
                printk(KERN_DEBUG
-                      pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+                       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
                goto error;
        }
 
@@ -533,9 +528,9 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
 
                        if (dev->_risc_virt_start_addr != NULL) {
                                risc_phys_jump_addr =
-                                   dev->_risc_phys_start_addr +
-                                   RISC_SYNC_INSTRUCTION_SIZE +
-                                   AUDIO_RISC_DMA_BUF_SIZE;
+                                       dev->_risc_phys_start_addr +
+                                       RISC_SYNC_INSTRUCTION_SIZE +
+                                       AUDIO_RISC_DMA_BUF_SIZE;
 
                                rp = cx25821_risc_field_upstream_audio(dev,
                                                dev->_risc_virt_start_addr + 1,
@@ -632,7 +627,7 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
                /* 10 millisecond timeout */
                if (count++ > 1000) {
                        pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
-                              __func__);
+                               __func__);
                        return;
                }
 
@@ -661,9 +656,9 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
 
        /* Set the input mode to 16-bit */
        tmp = cx_read(sram_ch->aud_cfg);
-       tmp |=
-           FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
-           FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;
+       tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+               FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D |
+               FLD_AUD_SONY_MODE;
        cx_write(sram_ch->aud_cfg, tmp);
 
        /* Read and write back the interrupt status register to clear it */
@@ -678,12 +673,11 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
        tmp = cx_read(sram_ch->int_msk);
        cx_write(sram_ch->int_msk, tmp |= _intr_msk);
 
-       err =
-           request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
                        IRQF_SHARED, dev->name, dev);
        if (err < 0) {
-               pr_err("%s: can't get upstream IRQ %d\n",
-                      dev->name, dev->pci->irq);
+               pr_err("%s: can't get upstream IRQ %d\n", dev->name,
+                               dev->pci->irq);
                goto fail_irq;
        }
 
@@ -726,7 +720,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 
        if (!dev->_irq_audio_queues) {
                printk(KERN_DEBUG
-                      pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+                       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
                return -ENOMEM;
        }
 
@@ -739,33 +733,30 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 
        if (dev->input_audiofilename) {
                str_length = strlen(dev->input_audiofilename);
-               dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_audiofilename = kmemdup(dev->input_audiofilename,
+                                             str_length + 1, GFP_KERNEL);
 
                if (!dev->_audiofilename)
                        goto error;
 
-               memcpy(dev->_audiofilename, dev->input_audiofilename,
-                      str_length + 1);
-
                /* Default if filename is empty string */
                if (strcmp(dev->input_audiofilename, "") == 0)
                        dev->_audiofilename = "/root/audioGOOD.wav";
        } else {
                str_length = strlen(_defaultAudioName);
-               dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_audiofilename = kmemdup(_defaultAudioName,
+                                             str_length + 1, GFP_KERNEL);
 
                if (!dev->_audiofilename)
                        goto error;
-
-               memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);
        }
 
        retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
                                                        _line_size, 0);
 
        dev->audio_upstream_riscbuf_size =
-           AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
-           RISC_SYNC_INSTRUCTION_SIZE;
+               AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+               RISC_SYNC_INSTRUCTION_SIZE;
        dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
 
        /* Allocating buffers and prepare RISC program */
@@ -773,7 +764,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
                                                        _line_size);
        if (retval < 0) {
                pr_err("%s: Failed to set up Audio upstream buffers!\n",
-                      dev->name);
+                       dev->name);
                goto error;
        }
        /* Start RISC engine */
index 8eb55b7b88cbd19f010b390521587807edffaa0a..1fc2d24f5110ac400e80f94ec5112ba4f0bc42c7 100644 (file)
 #ifndef __CX25821_AUDIO_H__
 #define __CX25821_AUDIO_H__
 
-#define USE_RISC_NOOP               1
-#define LINES_PER_BUFFER            15
-#define AUDIO_LINE_SIZE             128
+#define USE_RISC_NOOP          1
+#define LINES_PER_BUFFER       15
+#define AUDIO_LINE_SIZE                128
 
 /* Number of buffer programs to use at once. */
-#define NUMBER_OF_PROGRAMS  8
+#define NUMBER_OF_PROGRAMS     8
 
 /*
  * Max size of the RISC program for a buffer. - worst case is 2 writes per line
  * Space is also added for the 4 no-op instructions added on the end.
  */
 #ifndef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE     \
-       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
-       RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#define MAX_BUFFER_PROGRAM_SIZE                                                \
+       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
+        RISC_WRITECR_INSTRUCTION_SIZE * 4)
 #endif
 
 /* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
 #ifdef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE     \
-       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
-       RISC_NOOP_INSTRUCTION_SIZE * 4)
+#define MAX_BUFFER_PROGRAM_SIZE                                                \
+       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
+        RISC_NOOP_INSTRUCTION_SIZE * 4)
 #endif
 
 /* Sizes of various instructions in bytes.  Used when adding instructions. */
-#define RISC_WRITE_INSTRUCTION_SIZE 12
-#define RISC_JUMP_INSTRUCTION_SIZE  12
-#define RISC_SKIP_INSTRUCTION_SIZE  4
-#define RISC_SYNC_INSTRUCTION_SIZE  4
-#define RISC_WRITECR_INSTRUCTION_SIZE  16
-#define RISC_NOOP_INSTRUCTION_SIZE 4
-
-#define MAX_AUDIO_DMA_BUFFER_SIZE      \
-(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)
+#define RISC_WRITE_INSTRUCTION_SIZE    12
+#define RISC_JUMP_INSTRUCTION_SIZE     12
+#define RISC_SKIP_INSTRUCTION_SIZE     4
+#define RISC_SYNC_INSTRUCTION_SIZE     4
+#define RISC_WRITECR_INSTRUCTION_SIZE  16
+#define RISC_NOOP_INSTRUCTION_SIZE     4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE                                      \
+       (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS +                 \
+        RISC_SYNC_INSTRUCTION_SIZE)
 
 #endif
index 6ace60313b4907a1f090086d4579bd88d3caf185..99988c988095d0259bf6963a4971b81b376c17f9 100644 (file)
@@ -67,6 +67,6 @@ void cx25821_card_setup(struct cx25821_dev *dev)
        if (dev->i2c_bus[0].i2c_rc == 0) {
                dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
                tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
-                             sizeof(eeprom));
+                               sizeof(eeprom));
        }
 }
index a7fa38f9594e8356a4a180af2d2b5c85fbaa6474..f617474f907317eb39c8071e46660a8c48d23554 100644 (file)
@@ -804,8 +804,8 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
                              u32 format)
 {
        if (channel_select <= 7 && channel_select >= 0) {
-               cx_write(dev->channels[channel_select].
-                       sram_channels->pix_frmt, format);
+               cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
+                               format);
                dev->channels[channel_select].pixel_formats = format;
        }
 }
@@ -855,21 +855,19 @@ static void cx25821_initialize(struct cx25821_dev *dev)
        }
 
        cx25821_sram_channel_setup_audio(dev,
-                               dev->channels[SRAM_CH08].sram_channels,
-                               128, 0);
+                       dev->channels[SRAM_CH08].sram_channels, 128, 0);
 
        cx25821_gpio_init(dev);
 }
 
 static int cx25821_get_resources(struct cx25821_dev *dev)
 {
-       if (request_mem_region
-           (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
-            dev->name))
+       if (request_mem_region(pci_resource_start(dev->pci, 0),
+                               pci_resource_len(dev->pci, 0), dev->name))
                return 0;
 
        pr_err("%s: can't get MMIO memory @ 0x%llx\n",
-              dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+               dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
 
        return -EBUSY;
 }
@@ -972,8 +970,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
        dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
 
        if (!dev->lmmio) {
-               CX25821_ERR
-                   ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+               CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
                cx25821_iounmap(dev);
                return -ENOMEM;
        }
@@ -994,7 +991,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
  *  cx25821_i2c_register(&dev->i2c_bus[2]); */
 
        CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
-                    dev->i2c_bus[0].i2c_rc);
+                       dev->i2c_bus[0].i2c_rc);
 
        cx25821_card_setup(dev);
 
@@ -1004,9 +1001,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
        cx25821_video_register(dev);
 
        /* register IOCTL device */
-       dev->ioctl_dev =
-          cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template,
-                             "video");
+       dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci,
+                       &cx25821_videoioctl_template, "video");
 
        if (video_register_device
            (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
@@ -1103,16 +1099,15 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
                }
                if (bpl <= sg_dma_len(sg) - offset) {
                        /* fits into current chunk */
-                       *(rp++) =
-                           cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL |
+                                       bpl);
                        *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
                        *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
                        offset += bpl;
                } else {
                        /* scanline needs to be split */
                        todo = bpl;
-                       *(rp++) =
-                           cpu_to_le32(RISC_WRITE | RISC_SOL |
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL |
                                        (sg_dma_len(sg) - offset));
                        *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
                        *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
@@ -1120,8 +1115,8 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
                        offset = 0;
                        sg++;
                        while (todo > sg_dma_len(sg)) {
-                               *(rp++) =
-                                   cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
+                               *(rp++) = cpu_to_le32(RISC_WRITE |
+                                               sg_dma_len(sg));
                                *(rp++) = cpu_to_le32(sg_dma_address(sg));
                                *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
                                todo -= sg_dma_len(sg);
@@ -1160,8 +1155,8 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
           can cause next bpl to start close to a page border.  First DMA
           region may be smaller than PAGE_SIZE */
        /* write and jump need and extra dword */
-       instructions =
-           fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+       instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
+                       lines);
        instructions += 2;
        rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
 
@@ -1215,8 +1210,8 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
 
                if (bpl <= sg_dma_len(sg) - offset) {
                        /* fits into current chunk */
-                       *(rp++) =
-                           cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
+                       *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL |
+                                       bpl);
                        *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
                        *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
                        offset += bpl;
@@ -1224,7 +1219,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
                        /* scanline needs to be split */
                        todo = bpl;
                        *(rp++) = cpu_to_le32(RISC_WRITE | sol |
-                                             (sg_dma_len(sg) - offset));
+                                       (sg_dma_len(sg) - offset));
                        *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
                        *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
                        todo -= (sg_dma_len(sg) - offset);
@@ -1232,7 +1227,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
                        sg++;
                        while (todo > sg_dma_len(sg)) {
                                *(rp++) = cpu_to_le32(RISC_WRITE |
-                                                     sg_dma_len(sg));
+                                               sg_dma_len(sg));
                                *(rp++) = cpu_to_le32(sg_dma_address(sg));
                                *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
                                todo -= sg_dma_len(sg);
@@ -1339,8 +1334,8 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id)
                                sram_channels->int_stat);
 
                        if (vid_status)
-                               handled +=
-                               cx25821_video_irq(dev, i, vid_status);
+                               handled += cx25821_video_irq(dev, i,
+                                               vid_status);
 
                        cx_write(PCI_INT_STAT, mask[i]);
                }
@@ -1427,9 +1422,8 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
                goto fail_irq;
        }
 
-       err =
-           request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED,
-                       dev->name, dev);
+       err = request_irq(pci_dev->irq, cx25821_irq,
+                       IRQF_SHARED, dev->name, dev);
 
        if (err < 0) {
                pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
@@ -1512,6 +1506,5 @@ static void __exit cx25821_fini(void)
        pci_unregister_driver(&cx25821_pci_driver);
 }
 
-
 module_init(cx25821_init);
 module_exit(cx25821_fini);
index 4d3d0ce407856ba5753580e0a81835b0e24ab8bb..12d7300fa1e9e9f8563f065025c088099a707e58 100644 (file)
@@ -252,8 +252,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
                } 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);
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i],
+                                       msgs[i + 1].len);
 
                        if (retval < 0)
                                goto err;
@@ -276,10 +276,8 @@ err:
 
 static u32 cx25821_functionality(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_SMBUS_EMUL |
-           I2C_FUNC_I2C |
-           I2C_FUNC_SMBUS_WORD_DATA |
-           I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
 }
 
 static struct i2c_algorithm cx25821_i2c_algo_template = {
@@ -300,7 +298,7 @@ static struct i2c_client cx25821_i2c_client_template = {
        .name = "cx25821 internal",
 };
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int cx25821_i2c_register(struct cx25821_i2c *bus)
 {
        struct cx25821_dev *dev = bus->dev;
index 60d197f575560ab69ea79e49635b47019094b6c0..7a9e6470ba227db92d2a26fc89c83388fa6c3d89 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _MEDUSA_DEF_H_
 #define _MEDUSA_DEF_H_
 
-/* Video deocder that we supported */
+/* Video decoder that we supported */
 #define VDEC_A         0
 #define VDEC_B         1
 #define VDEC_C         2
@@ -34,9 +34,9 @@
 #define VDEC_H         7
 
 /* end of display sequence */
-#define END_OF_SEQ                                     0xF;
+#define END_OF_SEQ     0xF;
 
 /* registry string size */
-#define MAX_REGISTRY_SZ                                        40;
+#define MAX_REGISTRY_SZ        40;
 
 #endif
index 1c1c228352d10cb85e96436a9520c2fbf7185d58..c98ac946b277d9e33a4f8d86c29a3c7ada7fe4ff 100644 (file)
 #define        HOST_REGISTER2                          0x0001
 
 /* Chip Configuration Registers */
-#define        CHIP_CTRL                                       0x0100
-#define        AFE_AB_CTRL                                     0x0104
-#define        AFE_CD_CTRL                                     0x0108
-#define        AFE_EF_CTRL                                     0x010C
-#define        AFE_GH_CTRL                                     0x0110
+#define        CHIP_CTRL                               0x0100
+#define        AFE_AB_CTRL                             0x0104
+#define        AFE_CD_CTRL                             0x0108
+#define        AFE_EF_CTRL                             0x010C
+#define        AFE_GH_CTRL                             0x0110
 #define        DENC_AB_CTRL                            0x0114
-#define        BYP_AB_CTRL                                     0x0118
-#define        MON_A_CTRL                                      0x011C
-#define        DISP_SEQ_A                                      0x0120
-#define        DISP_SEQ_B                                      0x0124
-#define        DISP_AB_CNT                                     0x0128
-#define        DISP_CD_CNT                                     0x012C
-#define        DISP_EF_CNT                                     0x0130
-#define        DISP_GH_CNT                                     0x0134
-#define        DISP_IJ_CNT                                     0x0138
-#define        PIN_OE_CTRL                                     0x013C
+#define        BYP_AB_CTRL                             0x0118
+#define        MON_A_CTRL                              0x011C
+#define        DISP_SEQ_A                              0x0120
+#define        DISP_SEQ_B                              0x0124
+#define        DISP_AB_CNT                             0x0128
+#define        DISP_CD_CNT                             0x012C
+#define        DISP_EF_CNT                             0x0130
+#define        DISP_GH_CNT                             0x0134
+#define        DISP_IJ_CNT                             0x0138
+#define        PIN_OE_CTRL                             0x013C
 #define        PIN_SPD_CTRL                            0x0140
 #define        PIN_SPD_CTRL2                           0x0144
 #define        IRQ_STAT_CTRL                           0x0148
@@ -51,8 +51,8 @@
 #define        POWER_CTRL_CD                           0x0150
 #define        POWER_CTRL_EF                           0x0154
 #define        POWER_CTRL_GH                           0x0158
-#define        TUNE_CTRL                                       0x015C
-#define        BIAS_CTRL                                       0x0160
+#define        TUNE_CTRL                               0x015C
+#define        BIAS_CTRL                               0x0160
 #define        AFE_AB_DIAG_CTRL                        0x0164
 #define        AFE_CD_DIAG_CTRL                        0x0168
 #define        AFE_EF_DIAG_CTRL                        0x016C
 #define        PLL_CD_DIAG_CTRL                        0x0178
 #define        PLL_EF_DIAG_CTRL                        0x017C
 #define        PLL_GH_DIAG_CTRL                        0x0180
-#define        TEST_CTRL                                       0x0184
-#define        BIST_STAT                                       0x0188
-#define        BIST_STAT2                                      0x018C
-#define        BIST_VID_PLL_AB_STAT            0x0190
-#define        BIST_VID_PLL_CD_STAT            0x0194
-#define        BIST_VID_PLL_EF_STAT            0x0198
-#define        BIST_VID_PLL_GH_STAT            0x019C
+#define        TEST_CTRL                               0x0184
+#define        BIST_STAT                               0x0188
+#define        BIST_STAT2                              0x018C
+#define        BIST_VID_PLL_AB_STAT                    0x0190
+#define        BIST_VID_PLL_CD_STAT                    0x0194
+#define        BIST_VID_PLL_EF_STAT                    0x0198
+#define        BIST_VID_PLL_GH_STAT                    0x019C
 #define        DLL_DIAG_CTRL                           0x01A0
 #define        DEV_CH_ID_CTRL                          0x01A4
 #define        ABIST_CTRL_STATUS                       0x01A8
-#define        ABIST_FREQ                                      0x01AC
+#define        ABIST_FREQ                              0x01AC
 #define        ABIST_GOERT_SHIFT                       0x01B0
 #define        ABIST_COEF12                            0x01B4
 #define        ABIST_COEF34                            0x01B8
 #define        ABIST_CLAMP_E                           0x01F4
 #define        ABIST_CLAMP_F                           0x01F8
 
-/*              Digital Video Encoder A Registers */
-#define        DENC_A_REG_1                                    0x0200
-#define        DENC_A_REG_2                                    0x0204
-#define        DENC_A_REG_3                                    0x0208
-#define        DENC_A_REG_4                                    0x020C
-#define        DENC_A_REG_5                                    0x0210
-#define        DENC_A_REG_6                                    0x0214
-#define        DENC_A_REG_7                                    0x0218
-#define        DENC_A_REG_8                                    0x021C
+/* Digital Video Encoder A Registers */
+#define        DENC_A_REG_1                            0x0200
+#define        DENC_A_REG_2                            0x0204
+#define        DENC_A_REG_3                            0x0208
+#define        DENC_A_REG_4                            0x020C
+#define        DENC_A_REG_5                            0x0210
+#define        DENC_A_REG_6                            0x0214
+#define        DENC_A_REG_7                            0x0218
+#define        DENC_A_REG_8                            0x021C
 
-/*      Digital Video Encoder B Registers */
-#define        DENC_B_REG_1                                    0x0300
-#define        DENC_B_REG_2                                    0x0304
-#define        DENC_B_REG_3                                    0x0308
-#define        DENC_B_REG_4                                    0x030C
-#define        DENC_B_REG_5                                    0x0310
-#define        DENC_B_REG_6                                    0x0314
-#define        DENC_B_REG_7                                    0x0318
-#define        DENC_B_REG_8                                    0x031C
+/* Digital Video Encoder B Registers */
+#define        DENC_B_REG_1                            0x0300
+#define        DENC_B_REG_2                            0x0304
+#define        DENC_B_REG_3                            0x0308
+#define        DENC_B_REG_4                            0x030C
+#define        DENC_B_REG_5                            0x0310
+#define        DENC_B_REG_6                            0x0314
+#define        DENC_B_REG_7                            0x0318
+#define        DENC_B_REG_8                            0x031C
 
-/*              Video Decoder A Registers */
-#define        MODE_CTRL                                               0x1000
-#define        OUT_CTRL1                                               0x1004
-#define        OUT_CTRL_NS                                             0x1008
-#define        GEN_STAT                                                0x100C
-#define        INT_STAT_MASK                                   0x1010
-#define        LUMA_CTRL                                               0x1014
-#define        CHROMA_CTRL                                             0x1018
-#define        CRUSH_CTRL                                              0x101C
-#define        HORIZ_TIM_CTRL                                  0x1020
-#define        VERT_TIM_CTRL                                   0x1024
-#define        MISC_TIM_CTRL                                   0x1028
-#define        FIELD_COUNT                                             0x102C
-#define        HSCALE_CTRL                                             0x1030
-#define        VSCALE_CTRL                                             0x1034
-#define        MAN_VGA_CTRL                                    0x1038
-#define        MAN_AGC_CTRL                                    0x103C
-#define        DFE_CTRL1                                               0x1040
-#define        DFE_CTRL2                                               0x1044
-#define        DFE_CTRL3                                               0x1048
-#define        PLL_CTRL                                                0x104C
-#define        PLL_CTRL_FAST                                   0x1050
-#define        HTL_CTRL                                                0x1054
-#define        SRC_CFG                                                 0x1058
-#define        SC_STEP_SIZE                                    0x105C
-#define        SC_CONVERGE_CTRL                                0x1060
-#define        SC_LOOP_CTRL                                    0x1064
-#define        COMB_2D_HFS_CFG                                 0x1068
-#define        COMB_2D_HFD_CFG                                 0x106C
-#define        COMB_2D_LF_CFG                                  0x1070
-#define        COMB_2D_BLEND                                   0x1074
-#define        COMB_MISC_CTRL                                  0x1078
+/* Video Decoder A Registers */
+#define        MODE_CTRL                               0x1000
+#define        OUT_CTRL1                               0x1004
+#define        OUT_CTRL_NS                             0x1008
+#define        GEN_STAT                                0x100C
+#define        INT_STAT_MASK                           0x1010
+#define        LUMA_CTRL                               0x1014
+#define        CHROMA_CTRL                             0x1018
+#define        CRUSH_CTRL                              0x101C
+#define        HORIZ_TIM_CTRL                          0x1020
+#define        VERT_TIM_CTRL                           0x1024
+#define        MISC_TIM_CTRL                           0x1028
+#define        FIELD_COUNT                             0x102C
+#define        HSCALE_CTRL                             0x1030
+#define        VSCALE_CTRL                             0x1034
+#define        MAN_VGA_CTRL                            0x1038
+#define        MAN_AGC_CTRL                            0x103C
+#define        DFE_CTRL1                               0x1040
+#define        DFE_CTRL2                               0x1044
+#define        DFE_CTRL3                               0x1048
+#define        PLL_CTRL                                0x104C
+#define        PLL_CTRL_FAST                           0x1050
+#define        HTL_CTRL                                0x1054
+#define        SRC_CFG                                 0x1058
+#define        SC_STEP_SIZE                            0x105C
+#define        SC_CONVERGE_CTRL                        0x1060
+#define        SC_LOOP_CTRL                            0x1064
+#define        COMB_2D_HFS_CFG                         0x1068
+#define        COMB_2D_HFD_CFG                         0x106C
+#define        COMB_2D_LF_CFG                          0x1070
+#define        COMB_2D_BLEND                           0x1074
+#define        COMB_MISC_CTRL                          0x1078
 #define        COMB_FLAT_THRESH_CTRL                   0x107C
-#define        COMB_TEST                                               0x1080
-#define        BP_MISC_CTRL                                    0x1084
-#define        VCR_DET_CTRL                                    0x1088
-#define        NOISE_DET_CTRL                                  0x108C
+#define        COMB_TEST                               0x1080
+#define        BP_MISC_CTRL                            0x1084
+#define        VCR_DET_CTRL                            0x1088
+#define        NOISE_DET_CTRL                          0x108C
 #define        COMB_FLAT_NOISE_CTRL                    0x1090
-#define        VERSION                                                 0x11F8
-#define        SOFT_RST_CTRL                                   0x11FC
+#define        VERSION                                 0x11F8
+#define        SOFT_RST_CTRL                           0x11FC
 
-/*      Video Decoder B Registers */
-#define        VDEC_B_MODE_CTRL                                0x1200
-#define        VDEC_B_OUT_CTRL1                                0x1204
-#define        VDEC_B_OUT_CTRL_NS                              0x1208
-#define        VDEC_B_GEN_STAT                                 0x120C
+/* Video Decoder B Registers */
+#define        VDEC_B_MODE_CTRL                        0x1200
+#define        VDEC_B_OUT_CTRL1                        0x1204
+#define        VDEC_B_OUT_CTRL_NS                      0x1208
+#define        VDEC_B_GEN_STAT                         0x120C
 #define        VDEC_B_INT_STAT_MASK                    0x1210
-#define        VDEC_B_LUMA_CTRL                                0x1214
-#define        VDEC_B_CHROMA_CTRL                              0x1218
-#define        VDEC_B_CRUSH_CTRL                               0x121C
+#define        VDEC_B_LUMA_CTRL                        0x1214
+#define        VDEC_B_CHROMA_CTRL                      0x1218
+#define        VDEC_B_CRUSH_CTRL                       0x121C
 #define        VDEC_B_HORIZ_TIM_CTRL                   0x1220
 #define        VDEC_B_VERT_TIM_CTRL                    0x1224
 #define        VDEC_B_MISC_TIM_CTRL                    0x1228
-#define        VDEC_B_FIELD_COUNT                              0x122C
-#define        VDEC_B_HSCALE_CTRL                              0x1230
-#define        VDEC_B_VSCALE_CTRL                              0x1234
-#define        VDEC_B_MAN_VGA_CTRL                             0x1238
-#define        VDEC_B_MAN_AGC_CTRL                             0x123C
-#define        VDEC_B_DFE_CTRL1                                0x1240
-#define        VDEC_B_DFE_CTRL2                                0x1244
-#define        VDEC_B_DFE_CTRL3                                0x1248
-#define        VDEC_B_PLL_CTRL                                 0x124C
+#define        VDEC_B_FIELD_COUNT                      0x122C
+#define        VDEC_B_HSCALE_CTRL                      0x1230
+#define        VDEC_B_VSCALE_CTRL                      0x1234
+#define        VDEC_B_MAN_VGA_CTRL                     0x1238
+#define        VDEC_B_MAN_AGC_CTRL                     0x123C
+#define        VDEC_B_DFE_CTRL1                        0x1240
+#define        VDEC_B_DFE_CTRL2                        0x1244
+#define        VDEC_B_DFE_CTRL3                        0x1248
+#define        VDEC_B_PLL_CTRL                         0x124C
 #define        VDEC_B_PLL_CTRL_FAST                    0x1250
-#define        VDEC_B_HTL_CTRL                                 0x1254
-#define        VDEC_B_SRC_CFG                                  0x1258
-#define        VDEC_B_SC_STEP_SIZE                             0x125C
+#define        VDEC_B_HTL_CTRL                         0x1254
+#define        VDEC_B_SRC_CFG                          0x1258
+#define        VDEC_B_SC_STEP_SIZE                     0x125C
 #define        VDEC_B_SC_CONVERGE_CTRL                 0x1260
-#define        VDEC_B_SC_LOOP_CTRL                             0x1264
+#define        VDEC_B_SC_LOOP_CTRL                     0x1264
 #define        VDEC_B_COMB_2D_HFS_CFG                  0x1268
 #define        VDEC_B_COMB_2D_HFD_CFG                  0x126C
 #define        VDEC_B_COMB_2D_LF_CFG                   0x1270
 #define        VDEC_B_COMB_2D_BLEND                    0x1274
 #define        VDEC_B_COMB_MISC_CTRL                   0x1278
-#define        VDEC_B_COMB_FLAT_THRESH_CTRL    0x127C
-#define        VDEC_B_COMB_TEST                                0x1280
-#define        VDEC_B_BP_MISC_CTRL                             0x1284
-#define        VDEC_B_VCR_DET_CTRL                             0x1288
+#define        VDEC_B_COMB_FLAT_THRESH_CTRL            0x127C
+#define        VDEC_B_COMB_TEST                        0x1280
+#define        VDEC_B_BP_MISC_CTRL                     0x1284
+#define        VDEC_B_VCR_DET_CTRL                     0x1288
 #define        VDEC_B_NOISE_DET_CTRL                   0x128C
 #define        VDEC_B_COMB_FLAT_NOISE_CTRL             0x1290
-#define        VDEC_B_VERSION                                  0x13F8
+#define        VDEC_B_VERSION                          0x13F8
 #define        VDEC_B_SOFT_RST_CTRL                    0x13FC
 
 /* Video Decoder C Registers */
-#define        VDEC_C_MODE_CTRL                                0x1400
-#define        VDEC_C_OUT_CTRL1                                0x1404
-#define        VDEC_C_OUT_CTRL_NS                              0x1408
-#define        VDEC_C_GEN_STAT                                 0x140C
+#define        VDEC_C_MODE_CTRL                        0x1400
+#define        VDEC_C_OUT_CTRL1                        0x1404
+#define        VDEC_C_OUT_CTRL_NS                      0x1408
+#define        VDEC_C_GEN_STAT                         0x140C
 #define        VDEC_C_INT_STAT_MASK                    0x1410
-#define VDEC_C_LUMA_CTRL                               0x1414
-#define VDEC_C_CHROMA_CTRL                             0x1418
-#define        VDEC_C_CRUSH_CTRL                               0x141C
+#define VDEC_C_LUMA_CTRL                       0x1414
+#define VDEC_C_CHROMA_CTRL                     0x1418
+#define        VDEC_C_CRUSH_CTRL                       0x141C
 #define        VDEC_C_HORIZ_TIM_CTRL                   0x1420
 #define        VDEC_C_VERT_TIM_CTRL                    0x1424
 #define        VDEC_C_MISC_TIM_CTRL                    0x1428
-#define        VDEC_C_FIELD_COUNT                              0x142C
-#define        VDEC_C_HSCALE_CTRL                              0x1430
-#define        VDEC_C_VSCALE_CTRL                              0x1434
-#define        VDEC_C_MAN_VGA_CTRL                             0x1438
-#define        VDEC_C_MAN_AGC_CTRL                             0x143C
-#define        VDEC_C_DFE_CTRL1                                0x1440
-#define        VDEC_C_DFE_CTRL2                                0x1444
-#define        VDEC_C_DFE_CTRL3                                0x1448
-#define        VDEC_C_PLL_CTRL                                 0x144C
+#define        VDEC_C_FIELD_COUNT                      0x142C
+#define        VDEC_C_HSCALE_CTRL                      0x1430
+#define        VDEC_C_VSCALE_CTRL                      0x1434
+#define        VDEC_C_MAN_VGA_CTRL                     0x1438
+#define        VDEC_C_MAN_AGC_CTRL                     0x143C
+#define        VDEC_C_DFE_CTRL1                        0x1440
+#define        VDEC_C_DFE_CTRL2                        0x1444
+#define        VDEC_C_DFE_CTRL3                        0x1448
+#define        VDEC_C_PLL_CTRL                         0x144C
 #define        VDEC_C_PLL_CTRL_FAST                    0x1450
-#define        VDEC_C_HTL_CTRL                                 0x1454
-#define        VDEC_C_SRC_CFG                                  0x1458
-#define        VDEC_C_SC_STEP_SIZE                             0x145C
+#define        VDEC_C_HTL_CTRL                         0x1454
+#define        VDEC_C_SRC_CFG                          0x1458
+#define        VDEC_C_SC_STEP_SIZE                     0x145C
 #define        VDEC_C_SC_CONVERGE_CTRL                 0x1460
-#define        VDEC_C_SC_LOOP_CTRL                             0x1464
+#define        VDEC_C_SC_LOOP_CTRL                     0x1464
 #define        VDEC_C_COMB_2D_HFS_CFG                  0x1468
 #define        VDEC_C_COMB_2D_HFD_CFG                  0x146C
 #define        VDEC_C_COMB_2D_LF_CFG                   0x1470
 #define        VDEC_C_COMB_2D_BLEND                    0x1474
 #define        VDEC_C_COMB_MISC_CTRL                   0x1478
-#define        VDEC_C_COMB_FLAT_THRESH_CTRL    0x147C
-#define        VDEC_C_COMB_TEST                                0x1480
-#define        VDEC_C_BP_MISC_CTRL                             0x1484
-#define        VDEC_C_VCR_DET_CTRL                             0x1488
+#define        VDEC_C_COMB_FLAT_THRESH_CTRL            0x147C
+#define        VDEC_C_COMB_TEST                        0x1480
+#define        VDEC_C_BP_MISC_CTRL                     0x1484
+#define        VDEC_C_VCR_DET_CTRL                     0x1488
 #define        VDEC_C_NOISE_DET_CTRL                   0x148C
 #define        VDEC_C_COMB_FLAT_NOISE_CTRL             0x1490
-#define        VDEC_C_VERSION                                  0x15F8
+#define        VDEC_C_VERSION                          0x15F8
 #define        VDEC_C_SOFT_RST_CTRL                    0x15FC
 
 /* Video Decoder D Registers */
-#define VDEC_D_MODE_CTRL                               0x1600
-#define VDEC_D_OUT_CTRL1                               0x1604
-#define VDEC_D_OUT_CTRL_NS                             0x1608
-#define VDEC_D_GEN_STAT                                        0x160C
+#define VDEC_D_MODE_CTRL                       0x1600
+#define VDEC_D_OUT_CTRL1                       0x1604
+#define VDEC_D_OUT_CTRL_NS                     0x1608
+#define VDEC_D_GEN_STAT                                0x160C
 #define VDEC_D_INT_STAT_MASK                   0x1610
-#define VDEC_D_LUMA_CTRL                               0x1614
-#define VDEC_D_CHROMA_CTRL                             0x1618
-#define VDEC_D_CRUSH_CTRL                              0x161C
+#define VDEC_D_LUMA_CTRL                       0x1614
+#define VDEC_D_CHROMA_CTRL                     0x1618
+#define VDEC_D_CRUSH_CTRL                      0x161C
 #define VDEC_D_HORIZ_TIM_CTRL                  0x1620
 #define VDEC_D_VERT_TIM_CTRL                   0x1624
 #define VDEC_D_MISC_TIM_CTRL                   0x1628
-#define VDEC_D_FIELD_COUNT                             0x162C
-#define VDEC_D_HSCALE_CTRL                             0x1630
-#define VDEC_D_VSCALE_CTRL                             0x1634
-#define VDEC_D_MAN_VGA_CTRL                            0x1638
-#define VDEC_D_MAN_AGC_CTRL                            0x163C
-#define VDEC_D_DFE_CTRL1                               0x1640
-#define VDEC_D_DFE_CTRL2                               0x1644
-#define VDEC_D_DFE_CTRL3                               0x1648
-#define VDEC_D_PLL_CTRL                                        0x164C
+#define VDEC_D_FIELD_COUNT                     0x162C
+#define VDEC_D_HSCALE_CTRL                     0x1630
+#define VDEC_D_VSCALE_CTRL                     0x1634
+#define VDEC_D_MAN_VGA_CTRL                    0x1638
+#define VDEC_D_MAN_AGC_CTRL                    0x163C
+#define VDEC_D_DFE_CTRL1                       0x1640
+#define VDEC_D_DFE_CTRL2                       0x1644
+#define VDEC_D_DFE_CTRL3                       0x1648
+#define VDEC_D_PLL_CTRL                                0x164C
 #define VDEC_D_PLL_CTRL_FAST                   0x1650
-#define VDEC_D_HTL_CTRL                                        0x1654
-#define VDEC_D_SRC_CFG                                 0x1658
-#define VDEC_D_SC_STEP_SIZE                            0x165C
+#define VDEC_D_HTL_CTRL                                0x1654
+#define VDEC_D_SRC_CFG                         0x1658
+#define VDEC_D_SC_STEP_SIZE                    0x165C
 #define VDEC_D_SC_CONVERGE_CTRL                        0x1660
-#define VDEC_D_SC_LOOP_CTRL                            0x1664
+#define VDEC_D_SC_LOOP_CTRL                    0x1664
 #define VDEC_D_COMB_2D_HFS_CFG                 0x1668
 #define VDEC_D_COMB_2D_HFD_CFG                 0x166C
 #define VDEC_D_COMB_2D_LF_CFG                  0x1670
 #define VDEC_D_COMB_2D_BLEND                   0x1674
 #define VDEC_D_COMB_MISC_CTRL                  0x1678
-#define VDEC_D_COMB_FLAT_THRESH_CTRL   0x167C
-#define VDEC_D_COMB_TEST                               0x1680
-#define VDEC_D_BP_MISC_CTRL                            0x1684
-#define VDEC_D_VCR_DET_CTRL                            0x1688
+#define VDEC_D_COMB_FLAT_THRESH_CTRL           0x167C
+#define VDEC_D_COMB_TEST                       0x1680
+#define VDEC_D_BP_MISC_CTRL                    0x1684
+#define VDEC_D_VCR_DET_CTRL                    0x1688
 #define VDEC_D_NOISE_DET_CTRL                  0x168C
 #define VDEC_D_COMB_FLAT_NOISE_CTRL            0x1690
-#define VDEC_D_VERSION                                 0x17F8
+#define VDEC_D_VERSION                         0x17F8
 #define VDEC_D_SOFT_RST_CTRL                   0x17FC
 
 /* Video Decoder E Registers */
-#define        VDEC_E_MODE_CTRL                                0x1800
-#define        VDEC_E_OUT_CTRL1                                0x1804
-#define        VDEC_E_OUT_CTRL_NS                              0x1808
-#define        VDEC_E_GEN_STAT                                 0x180C
+#define        VDEC_E_MODE_CTRL                        0x1800
+#define        VDEC_E_OUT_CTRL1                        0x1804
+#define        VDEC_E_OUT_CTRL_NS                      0x1808
+#define        VDEC_E_GEN_STAT                         0x180C
 #define        VDEC_E_INT_STAT_MASK                    0x1810
-#define        VDEC_E_LUMA_CTRL                                0x1814
-#define        VDEC_E_CHROMA_CTRL                              0x1818
-#define        VDEC_E_CRUSH_CTRL                               0x181C
+#define        VDEC_E_LUMA_CTRL                        0x1814
+#define        VDEC_E_CHROMA_CTRL                      0x1818
+#define        VDEC_E_CRUSH_CTRL                       0x181C
 #define        VDEC_E_HORIZ_TIM_CTRL                   0x1820
 #define        VDEC_E_VERT_TIM_CTRL                    0x1824
 #define        VDEC_E_MISC_TIM_CTRL                    0x1828
-#define        VDEC_E_FIELD_COUNT                              0x182C
-#define        VDEC_E_HSCALE_CTRL                              0x1830
-#define        VDEC_E_VSCALE_CTRL                              0x1834
-#define        VDEC_E_MAN_VGA_CTRL                             0x1838
-#define        VDEC_E_MAN_AGC_CTRL                             0x183C
-#define        VDEC_E_DFE_CTRL1                                0x1840
-#define        VDEC_E_DFE_CTRL2                                0x1844
-#define        VDEC_E_DFE_CTRL3                                0x1848
-#define        VDEC_E_PLL_CTRL                                 0x184C
+#define        VDEC_E_FIELD_COUNT                      0x182C
+#define        VDEC_E_HSCALE_CTRL                      0x1830
+#define        VDEC_E_VSCALE_CTRL                      0x1834
+#define        VDEC_E_MAN_VGA_CTRL                     0x1838
+#define        VDEC_E_MAN_AGC_CTRL                     0x183C
+#define        VDEC_E_DFE_CTRL1                        0x1840
+#define        VDEC_E_DFE_CTRL2                        0x1844
+#define        VDEC_E_DFE_CTRL3                        0x1848
+#define        VDEC_E_PLL_CTRL                         0x184C
 #define        VDEC_E_PLL_CTRL_FAST                    0x1850
-#define        VDEC_E_HTL_CTRL                                 0x1854
-#define        VDEC_E_SRC_CFG                                  0x1858
-#define        VDEC_E_SC_STEP_SIZE                             0x185C
+#define        VDEC_E_HTL_CTRL                         0x1854
+#define        VDEC_E_SRC_CFG                          0x1858
+#define        VDEC_E_SC_STEP_SIZE                     0x185C
 #define        VDEC_E_SC_CONVERGE_CTRL                 0x1860
-#define        VDEC_E_SC_LOOP_CTRL                             0x1864
+#define        VDEC_E_SC_LOOP_CTRL                     0x1864
 #define        VDEC_E_COMB_2D_HFS_CFG                  0x1868
 #define        VDEC_E_COMB_2D_HFD_CFG                  0x186C
 #define        VDEC_E_COMB_2D_LF_CFG                   0x1870
 #define        VDEC_E_COMB_2D_BLEND                    0x1874
 #define        VDEC_E_COMB_MISC_CTRL                   0x1878
-#define        VDEC_E_COMB_FLAT_THRESH_CTRL    0x187C
-#define        VDEC_E_COMB_TEST                                0x1880
-#define        VDEC_E_BP_MISC_CTRL                             0x1884
-#define        VDEC_E_VCR_DET_CTRL                             0x1888
+#define        VDEC_E_COMB_FLAT_THRESH_CTRL            0x187C
+#define        VDEC_E_COMB_TEST                        0x1880
+#define        VDEC_E_BP_MISC_CTRL                     0x1884
+#define        VDEC_E_VCR_DET_CTRL                     0x1888
 #define        VDEC_E_NOISE_DET_CTRL                   0x188C
 #define        VDEC_E_COMB_FLAT_NOISE_CTRL             0x1890
-#define        VDEC_E_VERSION                                  0x19F8
+#define        VDEC_E_VERSION                          0x19F8
 #define        VDEC_E_SOFT_RST_CTRL                    0x19FC
 
 /* Video Decoder F Registers */
-#define        VDEC_F_MODE_CTRL                                0x1A00
-#define        VDEC_F_OUT_CTRL1                                0x1A04
-#define        VDEC_F_OUT_CTRL_NS                              0x1A08
-#define        VDEC_F_GEN_STAT                                 0x1A0C
+#define        VDEC_F_MODE_CTRL                        0x1A00
+#define        VDEC_F_OUT_CTRL1                        0x1A04
+#define        VDEC_F_OUT_CTRL_NS                      0x1A08
+#define        VDEC_F_GEN_STAT                         0x1A0C
 #define        VDEC_F_INT_STAT_MASK                    0x1A10
-#define        VDEC_F_LUMA_CTRL                                0x1A14
-#define        VDEC_F_CHROMA_CTRL                              0x1A18
-#define        VDEC_F_CRUSH_CTRL                               0x1A1C
+#define        VDEC_F_LUMA_CTRL                        0x1A14
+#define        VDEC_F_CHROMA_CTRL                      0x1A18
+#define        VDEC_F_CRUSH_CTRL                       0x1A1C
 #define        VDEC_F_HORIZ_TIM_CTRL                   0x1A20
 #define        VDEC_F_VERT_TIM_CTRL                    0x1A24
 #define        VDEC_F_MISC_TIM_CTRL                    0x1A28
-#define        VDEC_F_FIELD_COUNT                              0x1A2C
-#define        VDEC_F_HSCALE_CTRL                              0x1A30
-#define        VDEC_F_VSCALE_CTRL                              0x1A34
-#define        VDEC_F_MAN_VGA_CTRL                             0x1A38
-#define        VDEC_F_MAN_AGC_CTRL                             0x1A3C
-#define        VDEC_F_DFE_CTRL1                                0x1A40
-#define        VDEC_F_DFE_CTRL2                                0x1A44
-#define        VDEC_F_DFE_CTRL3                                0x1A48
-#define        VDEC_F_PLL_CTRL                                 0x1A4C
+#define        VDEC_F_FIELD_COUNT                      0x1A2C
+#define        VDEC_F_HSCALE_CTRL                      0x1A30
+#define        VDEC_F_VSCALE_CTRL                      0x1A34
+#define        VDEC_F_MAN_VGA_CTRL                     0x1A38
+#define        VDEC_F_MAN_AGC_CTRL                     0x1A3C
+#define        VDEC_F_DFE_CTRL1                        0x1A40
+#define        VDEC_F_DFE_CTRL2                        0x1A44
+#define        VDEC_F_DFE_CTRL3                        0x1A48
+#define        VDEC_F_PLL_CTRL                         0x1A4C
 #define        VDEC_F_PLL_CTRL_FAST                    0x1A50
-#define        VDEC_F_HTL_CTRL                                 0x1A54
-#define        VDEC_F_SRC_CFG                                  0x1A58
-#define        VDEC_F_SC_STEP_SIZE                             0x1A5C
+#define        VDEC_F_HTL_CTRL                         0x1A54
+#define        VDEC_F_SRC_CFG                          0x1A58
+#define        VDEC_F_SC_STEP_SIZE                     0x1A5C
 #define        VDEC_F_SC_CONVERGE_CTRL                 0x1A60
-#define        VDEC_F_SC_LOOP_CTRL                             0x1A64
+#define        VDEC_F_SC_LOOP_CTRL                     0x1A64
 #define        VDEC_F_COMB_2D_HFS_CFG                  0x1A68
 #define        VDEC_F_COMB_2D_HFD_CFG                  0x1A6C
 #define        VDEC_F_COMB_2D_LF_CFG                   0x1A70
 #define        VDEC_F_COMB_2D_BLEND                    0x1A74
 #define        VDEC_F_COMB_MISC_CTRL                   0x1A78
-#define        VDEC_F_COMB_FLAT_THRESH_CTRL    0x1A7C
-#define        VDEC_F_COMB_TEST                                0x1A80
-#define        VDEC_F_BP_MISC_CTRL                             0x1A84
-#define        VDEC_F_VCR_DET_CTRL                             0x1A88
+#define        VDEC_F_COMB_FLAT_THRESH_CTRL            0x1A7C
+#define        VDEC_F_COMB_TEST                        0x1A80
+#define        VDEC_F_BP_MISC_CTRL                     0x1A84
+#define        VDEC_F_VCR_DET_CTRL                     0x1A88
 #define        VDEC_F_NOISE_DET_CTRL                   0x1A8C
 #define        VDEC_F_COMB_FLAT_NOISE_CTRL             0x1A90
-#define        VDEC_F_VERSION                                  0x1BF8
+#define        VDEC_F_VERSION                          0x1BF8
 #define        VDEC_F_SOFT_RST_CTRL                    0x1BFC
 
 /* Video Decoder G Registers */
-#define        VDEC_G_MODE_CTRL                                0x1C00
-#define        VDEC_G_OUT_CTRL1                                0x1C04
-#define        VDEC_G_OUT_CTRL_NS                              0x1C08
-#define        VDEC_G_GEN_STAT                                 0x1C0C
+#define        VDEC_G_MODE_CTRL                        0x1C00
+#define        VDEC_G_OUT_CTRL1                        0x1C04
+#define        VDEC_G_OUT_CTRL_NS                      0x1C08
+#define        VDEC_G_GEN_STAT                         0x1C0C
 #define        VDEC_G_INT_STAT_MASK                    0x1C10
-#define        VDEC_G_LUMA_CTRL                                0x1C14
-#define        VDEC_G_CHROMA_CTRL                              0x1C18
-#define        VDEC_G_CRUSH_CTRL                               0x1C1C
+#define        VDEC_G_LUMA_CTRL                        0x1C14
+#define        VDEC_G_CHROMA_CTRL                      0x1C18
+#define        VDEC_G_CRUSH_CTRL                       0x1C1C
 #define        VDEC_G_HORIZ_TIM_CTRL                   0x1C20
 #define        VDEC_G_VERT_TIM_CTRL                    0x1C24
 #define        VDEC_G_MISC_TIM_CTRL                    0x1C28
-#define        VDEC_G_FIELD_COUNT                              0x1C2C
-#define        VDEC_G_HSCALE_CTRL                              0x1C30
-#define        VDEC_G_VSCALE_CTRL                              0x1C34
-#define        VDEC_G_MAN_VGA_CTRL                             0x1C38
-#define        VDEC_G_MAN_AGC_CTRL                             0x1C3C
-#define        VDEC_G_DFE_CTRL1                                0x1C40
-#define        VDEC_G_DFE_CTRL2                                0x1C44
-#define        VDEC_G_DFE_CTRL3                                0x1C48
-#define        VDEC_G_PLL_CTRL                                 0x1C4C
+#define        VDEC_G_FIELD_COUNT                      0x1C2C
+#define        VDEC_G_HSCALE_CTRL                      0x1C30
+#define        VDEC_G_VSCALE_CTRL                      0x1C34
+#define        VDEC_G_MAN_VGA_CTRL                     0x1C38
+#define        VDEC_G_MAN_AGC_CTRL                     0x1C3C
+#define        VDEC_G_DFE_CTRL1                        0x1C40
+#define        VDEC_G_DFE_CTRL2                        0x1C44
+#define        VDEC_G_DFE_CTRL3                        0x1C48
+#define        VDEC_G_PLL_CTRL                         0x1C4C
 #define        VDEC_G_PLL_CTRL_FAST                    0x1C50
-#define        VDEC_G_HTL_CTRL                                 0x1C54
-#define        VDEC_G_SRC_CFG                                  0x1C58
-#define        VDEC_G_SC_STEP_SIZE                             0x1C5C
+#define        VDEC_G_HTL_CTRL                         0x1C54
+#define        VDEC_G_SRC_CFG                          0x1C58
+#define        VDEC_G_SC_STEP_SIZE                     0x1C5C
 #define        VDEC_G_SC_CONVERGE_CTRL                 0x1C60
-#define        VDEC_G_SC_LOOP_CTRL                             0x1C64
+#define        VDEC_G_SC_LOOP_CTRL                     0x1C64
 #define        VDEC_G_COMB_2D_HFS_CFG                  0x1C68
 #define        VDEC_G_COMB_2D_HFD_CFG                  0x1C6C
 #define        VDEC_G_COMB_2D_LF_CFG                   0x1C70
 #define        VDEC_G_COMB_2D_BLEND                    0x1C74
 #define        VDEC_G_COMB_MISC_CTRL                   0x1C78
-#define        VDEC_G_COMB_FLAT_THRESH_CTRL    0x1C7C
-#define        VDEC_G_COMB_TEST                                0x1C80
-#define        VDEC_G_BP_MISC_CTRL                             0x1C84
-#define        VDEC_G_VCR_DET_CTRL                             0x1C88
+#define        VDEC_G_COMB_FLAT_THRESH_CTRL            0x1C7C
+#define        VDEC_G_COMB_TEST                        0x1C80
+#define        VDEC_G_BP_MISC_CTRL                     0x1C84
+#define        VDEC_G_VCR_DET_CTRL                     0x1C88
 #define        VDEC_G_NOISE_DET_CTRL                   0x1C8C
 #define        VDEC_G_COMB_FLAT_NOISE_CTRL             0x1C90
-#define        VDEC_G_VERSION                                  0x1DF8
+#define        VDEC_G_VERSION                          0x1DF8
 #define        VDEC_G_SOFT_RST_CTRL                    0x1DFC
 
-/*              Video Decoder H Registers  */
-#define        VDEC_H_MODE_CTRL                                0x1E00
-#define        VDEC_H_OUT_CTRL1                                0x1E04
-#define        VDEC_H_OUT_CTRL_NS                              0x1E08
-#define        VDEC_H_GEN_STAT                                 0x1E0C
+/* Video Decoder H Registers  */
+#define        VDEC_H_MODE_CTRL                        0x1E00
+#define        VDEC_H_OUT_CTRL1                        0x1E04
+#define        VDEC_H_OUT_CTRL_NS                      0x1E08
+#define        VDEC_H_GEN_STAT                         0x1E0C
 #define        VDEC_H_INT_STAT_MASK                    0x1E1E
-#define        VDEC_H_LUMA_CTRL                                0x1E14
-#define        VDEC_H_CHROMA_CTRL                              0x1E18
-#define        VDEC_H_CRUSH_CTRL                               0x1E1C
+#define        VDEC_H_LUMA_CTRL                        0x1E14
+#define        VDEC_H_CHROMA_CTRL                      0x1E18
+#define        VDEC_H_CRUSH_CTRL                       0x1E1C
 #define        VDEC_H_HORIZ_TIM_CTRL                   0x1E20
 #define        VDEC_H_VERT_TIM_CTRL                    0x1E24
 #define        VDEC_H_MISC_TIM_CTRL                    0x1E28
-#define        VDEC_H_FIELD_COUNT                              0x1E2C
-#define        VDEC_H_HSCALE_CTRL                              0x1E30
-#define        VDEC_H_VSCALE_CTRL                              0x1E34
-#define        VDEC_H_MAN_VGA_CTRL                             0x1E38
-#define        VDEC_H_MAN_AGC_CTRL                             0x1E3C
-#define        VDEC_H_DFE_CTRL1                                0x1E40
-#define        VDEC_H_DFE_CTRL2                                0x1E44
-#define        VDEC_H_DFE_CTRL3                                0x1E48
-#define        VDEC_H_PLL_CTRL                                 0x1E4C
+#define        VDEC_H_FIELD_COUNT                      0x1E2C
+#define        VDEC_H_HSCALE_CTRL                      0x1E30
+#define        VDEC_H_VSCALE_CTRL                      0x1E34
+#define        VDEC_H_MAN_VGA_CTRL                     0x1E38
+#define        VDEC_H_MAN_AGC_CTRL                     0x1E3C
+#define        VDEC_H_DFE_CTRL1                        0x1E40
+#define        VDEC_H_DFE_CTRL2                        0x1E44
+#define        VDEC_H_DFE_CTRL3                        0x1E48
+#define        VDEC_H_PLL_CTRL                         0x1E4C
 #define        VDEC_H_PLL_CTRL_FAST                    0x1E50
-#define        VDEC_H_HTL_CTRL                                 0x1E54
-#define        VDEC_H_SRC_CFG                                  0x1E58
-#define        VDEC_H_SC_STEP_SIZE                             0x1E5C
+#define        VDEC_H_HTL_CTRL                         0x1E54
+#define        VDEC_H_SRC_CFG                          0x1E58
+#define        VDEC_H_SC_STEP_SIZE                     0x1E5C
 #define        VDEC_H_SC_CONVERGE_CTRL                 0x1E60
-#define        VDEC_H_SC_LOOP_CTRL                             0x1E64
+#define        VDEC_H_SC_LOOP_CTRL                     0x1E64
 #define        VDEC_H_COMB_2D_HFS_CFG                  0x1E68
 #define        VDEC_H_COMB_2D_HFD_CFG                  0x1E6C
 #define        VDEC_H_COMB_2D_LF_CFG                   0x1E70
 #define        VDEC_H_COMB_2D_BLEND                    0x1E74
 #define        VDEC_H_COMB_MISC_CTRL                   0x1E78
-#define        VDEC_H_COMB_FLAT_THRESH_CTRL    0x1E7C
-#define        VDEC_H_COMB_TEST                                0x1E80
-#define        VDEC_H_BP_MISC_CTRL                             0x1E84
-#define        VDEC_H_VCR_DET_CTRL                             0x1E88
+#define        VDEC_H_COMB_FLAT_THRESH_CTRL            0x1E7C
+#define        VDEC_H_COMB_TEST                        0x1E80
+#define        VDEC_H_BP_MISC_CTRL                     0x1E84
+#define        VDEC_H_VCR_DET_CTRL                     0x1E88
 #define        VDEC_H_NOISE_DET_CTRL                   0x1E8C
 #define        VDEC_H_COMB_FLAT_NOISE_CTRL             0x1E90
-#define        VDEC_H_VERSION                                  0x1FF8
+#define        VDEC_H_VERSION                          0x1FF8
 #define        VDEC_H_SOFT_RST_CTRL                    0x1FFC
 
 /*****************************************************************************/
 /* LUMA_CTRL register fields */
-#define VDEC_A_BRITE_CTRL                              0x1014
+#define VDEC_A_BRITE_CTRL                      0x1014
 #define VDEC_A_CNTRST_CTRL                     0x1015
 #define VDEC_A_PEAK_SEL                                0x1016
 
index fc780d0908dc61e54f255f7f7ca6c290df598274..298a68d98c2f3ac4bab0846715f440410f85d185 100644 (file)
@@ -99,82 +99,67 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev)
 
        for (i = 0; i < MAX_DECODERS; i++) {
                /* set video format NTSC-M */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), &tmp);
                value &= 0xFFFFFFF0;
                /* enable the fast locking mode bit[16] */
                value |= 0x10001;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), value);
 
                /* resolution NTSC 720x480 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
                value &= 0x00C00C00;
                value |= 0x612D0074;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     HORIZ_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), value);
 
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    VERT_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), &tmp);
                value &= 0x00C00C00;
                value |= 0x1C1E001A;    /* vblank_cnt + 2 to get camera ID */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     VERT_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), value);
 
                /* chroma subcarrier step size */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               SC_STEP_SIZE + (0x200 * i), 0x43E00000);
 
                /* enable VIP optional active */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    OUT_CTRL_NS + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), &tmp);
                value &= 0xFFFBFFFF;
                value |= 0x00040000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     OUT_CTRL_NS + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), value);
 
                /* enable VIP optional active (VIP_OPT_AL) for direct output. */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), &tmp);
                value &= 0xFFFBFFFF;
                value |= 0x00040000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), value);
 
                /*
                 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
                 * when the input switching rate < 16 fields
                */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    MISC_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), &tmp);
                /* disable special play detection */
                value = setBitAtPos(value, 14);
                value = clearBitAtPos(value, 15);
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     MISC_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), value);
 
                /* set vbi_gate_en to 0 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), &tmp);
                value = clearBitAtPos(value, 29);
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), value);
 
                /* Enable the generation of blue field output if no video */
                medusa_enable_bluefield_output(dev, i, 1);
@@ -182,61 +167,49 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev)
 
        for (i = 0; i < MAX_ENCODERS; i++) {
                /* NTSC hclock */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_1 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), &tmp);
                value &= 0xF000FC00;
                value |= 0x06B402D0;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_1 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), value);
 
                /* burst begin and burst end */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_2 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), &tmp);
                value &= 0xFF000000;
                value |= 0x007E9054;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_2 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), value);
 
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_3 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), &tmp);
                value &= 0xFC00FE00;
                value |= 0x00EC00F0;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_3 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), value);
 
                /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_4 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), &tmp);
                value &= 0x00FCFFFF;
                value |= 0x13020000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_4 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), value);
 
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_5 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), &tmp);
                value &= 0xFFFF0000;
                value |= 0x0000E575;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_5 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), value);
 
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
 
                /* Subcarrier Increment */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
        }
 
        /* set picture resolutions */
@@ -261,34 +234,27 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
        u32 value = 0, tmp = 0;
 
        /* Setup for 2D threshold */
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
-                             0x20002861);
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
-                             0x20002861);
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
-                             0x200A1023);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
 
        /* Setup flat chroma and luma thresholds */
-       value =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+       value = cx25821_i2c_read(&dev->i2c_bus[0],
+                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
        value &= 0x06230000;
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
 
        /* set comb 2D blend */
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
-                             0x210F0F0F);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
 
        /* COMB MISC CONTROL */
-       ret_val =
-           cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
-                             0x41120A7F);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
 
        return ret_val;
 }
@@ -304,83 +270,68 @@ static int medusa_initialize_pal(struct cx25821_dev *dev)
 
        for (i = 0; i < MAX_DECODERS; i++) {
                /* set video format PAL-BDGHI */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), &tmp);
                value &= 0xFFFFFFF0;
                /* enable the fast locking mode bit[16] */
                value |= 0x10004;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), value);
 
                /* resolution PAL 720x576 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
                value &= 0x00C00C00;
                value |= 0x632D007D;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     HORIZ_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), value);
 
                /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    VERT_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), &tmp);
                value &= 0x00C00C00;
                value |= 0x28240026;    /* vblank_cnt + 2 to get camera ID */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     VERT_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), value);
 
                /* chroma subcarrier step size */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
 
                /* enable VIP optional active */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    OUT_CTRL_NS + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), &tmp);
                value &= 0xFFFBFFFF;
                value |= 0x00040000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     OUT_CTRL_NS + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), value);
 
                /* enable VIP optional active (VIP_OPT_AL) for direct output. */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), &tmp);
                value &= 0xFFFBFFFF;
                value |= 0x00040000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), value);
 
                /*
                 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
                 * when the input switching rate < 16 fields
                 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    MISC_TIM_CTRL + (0x200 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), &tmp);
                /* disable special play detection */
                value = setBitAtPos(value, 14);
                value = clearBitAtPos(value, 15);
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     MISC_TIM_CTRL + (0x200 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), value);
 
                /* set vbi_gate_en to 0 */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
-                                    &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), &tmp);
                value = clearBitAtPos(value, 29);
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
-                                     value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), value);
 
                medusa_PALCombInit(dev, i);
 
@@ -390,62 +341,50 @@ static int medusa_initialize_pal(struct cx25821_dev *dev)
 
        for (i = 0; i < MAX_ENCODERS; i++) {
                /* PAL hclock */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_1 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), &tmp);
                value &= 0xF000FC00;
                value |= 0x06C002D0;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_1 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), value);
 
                /* burst begin and burst end */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_2 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), &tmp);
                value &= 0xFF000000;
                value |= 0x007E9754;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_2 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), value);
 
                /* hblank and vactive */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_3 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), &tmp);
                value &= 0xFC00FE00;
                value |= 0x00FC0120;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_3 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), value);
 
                /* set PAL vblank, phase alternation, 0 IRE pedestal */
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_4 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), &tmp);
                value &= 0x00FCFFFF;
                value |= 0x14010000;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_4 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), value);
 
-               value =
-                   cx25821_i2c_read(&dev->i2c_bus[0],
-                                    DENC_A_REG_5 + (0x100 * i), &tmp);
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), &tmp);
                value &= 0xFFFF0000;
                value |= 0x0000F078;
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_5 + (0x100 * i), value);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), value);
 
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
 
                /* Subcarrier Increment */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
        }
 
        /* set picture resolutions */
@@ -499,7 +438,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width,
 
        mutex_lock(&dev->lock);
 
-       /* validate the width - cannot be negative */
+       /* validate the width */
        if (width > MAX_WIDTH) {
                pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
                        __func__, width, MAX_WIDTH);
@@ -543,12 +482,10 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width,
 
        for (; decoder < decoder_count; decoder++) {
                /* write scaling values for each decoder */
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     HSCALE_CTRL + (0x200 * decoder), hscale);
-               ret_val =
-                   cx25821_i2c_write(&dev->i2c_bus[0],
-                                     VSCALE_CTRL + (0x200 * decoder), vscale);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               HSCALE_CTRL + (0x200 * decoder), hscale);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               VSCALE_CTRL + (0x200 * decoder), vscale);
        }
 
        mutex_unlock(&dev->lock);
@@ -606,8 +543,8 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
 }
 
 /* Map to Medusa register setting */
-static int mapM(int srcMin,
-               int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
+static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
+               int *dstVal)
 {
        int numerator;
        int denominator;
@@ -654,23 +591,19 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
        u32 val = 0, tmp = 0;
 
        mutex_lock(&dev->lock);
-       if ((brightness > VIDEO_PROCAMP_MAX)
-           || (brightness < VIDEO_PROCAMP_MIN)) {
+       if ((brightness > VIDEO_PROCAMP_MAX) ||
+           (brightness < VIDEO_PROCAMP_MIN)) {
                mutex_unlock(&dev->lock);
                return -1;
        }
-       ret_val =
-           mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
-                SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
        value = convert_to_twos(value, 8);
-       val =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
        val &= 0xFFFFFF00;
-       ret_val |=
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             VDEC_A_BRITE_CTRL + (0x200 * decoder),
-                             val | value);
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
        mutex_unlock(&dev->lock);
        return ret_val;
 }
@@ -688,17 +621,13 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
                return -1;
        }
 
-       ret_val =
-           mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
-                UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
-       val =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
        val &= 0xFFFFFF00;
-       ret_val |=
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             VDEC_A_CNTRST_CTRL + (0x200 * decoder),
-                             val | value);
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
 
        mutex_unlock(&dev->lock);
        return ret_val;
@@ -717,19 +646,16 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
                return -1;
        }
 
-       ret_val =
-           mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
-                SIGNED_BYTE_MAX, &value);
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
+                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
 
        value = convert_to_twos(value, 8);
-       val =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
        val &= 0xFFFFFF00;
 
-       ret_val |=
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
 
        mutex_unlock(&dev->lock);
        return ret_val;
@@ -743,33 +669,26 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
 
        mutex_lock(&dev->lock);
 
-       if ((saturation > VIDEO_PROCAMP_MAX)
-           || (saturation < VIDEO_PROCAMP_MIN)) {
+       if ((saturation > VIDEO_PROCAMP_MAX) ||
+           (saturation < VIDEO_PROCAMP_MIN)) {
                mutex_unlock(&dev->lock);
                return -1;
        }
 
-       ret_val =
-           mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
-                UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
 
-       val =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
        val &= 0xFFFFFF00;
-       ret_val |=
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             VDEC_A_USAT_CTRL + (0x200 * decoder),
-                             val | value);
-
-       val =
-           cx25821_i2c_read(&dev->i2c_bus[0],
-                            VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
+
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
        val &= 0xFFFFFF00;
-       ret_val |=
-           cx25821_i2c_write(&dev->i2c_bus[0],
-                             VDEC_A_VSAT_CTRL + (0x200 * decoder),
-                             val | value);
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
 
        mutex_unlock(&dev->lock);
        return ret_val;
@@ -830,9 +749,8 @@ int medusa_video_init(struct cx25821_dev *dev)
        /* select AFE clock to output mode */
        value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
        value &= 0x83FFFFFF;
-       ret_val =
-          cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
-                            value | 0x10000000);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+                       value | 0x10000000);
 
        if (ret_val < 0)
                goto error;
index 2a724ddfa53f1cfa226f8569a7d98dd68647391c..5a157cf4a95e38ca8b8f7800f01267ad85d14569 100644 (file)
@@ -65,9 +65,8 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
                *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
                *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
 
-               if ((lines <= NTSC_FIELD_HEIGHT)
-                   || (line < (NTSC_FIELD_HEIGHT - 1))
-                   || !(dev->_isNTSC_ch2)) {
+               if ((lines <= NTSC_FIELD_HEIGHT) ||
+                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
                        offset += dist_betwn_starts;
                }
        }
@@ -85,7 +84,7 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
 {
        unsigned int line, i;
        struct sram_channel *sram_ch =
-          dev->channels[dev->_channel2_upstream_select].sram_channels;
+               dev->channels[dev->_channel2_upstream_select].sram_channels;
        int dist_betwn_starts = bpl * 2;
 
        /* sync instruction */
@@ -103,9 +102,8 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
                *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
                *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
 
-               if ((lines <= NTSC_FIELD_HEIGHT)
-                   || (line < (NTSC_FIELD_HEIGHT - 1))
-                   || !(dev->_isNTSC_ch2)) {
+               if ((lines <= NTSC_FIELD_HEIGHT) ||
+                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
                        offset += dist_betwn_starts;
                }
 
@@ -173,7 +171,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
 
                fifo_enable = FIFO_DISABLE;
 
-              /* Even field */
+               /* Even field */
                rp = cx25821_risc_field_upstream_ch2(dev, rp,
                                dev->_data_buf_phys_addr_ch2 + databuf_offset,
                                bottom_offset, 0x200, bpl, singlefield_lines,
@@ -189,9 +187,9 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
                }
 
               /*
-                 Loop to 2ndFrameRISC or to Start of
-                 Risc program & generate IRQ
-              */
+               * Loop to 2ndFrameRISC or to Start of
+               * Risc program & generate IRQ
+               */
                *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
                *(rp++) = cpu_to_le32(risc_phys_jump_addr);
                *(rp++) = cpu_to_le32(0);
@@ -203,7 +201,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
 void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
 {
        struct sram_channel *sram_ch =
-          dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
        u32 tmp = 0;
 
        if (!dev->_is_running_ch2) {
@@ -262,9 +260,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
        struct file *myfile;
        int frame_index_temp = dev->_frame_index_ch2;
        int i = 0;
-       int line_size =
-           (dev->_pixel_format_ch2 ==
-            PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
        int frame_size = 0;
        int frame_offset = 0;
        ssize_t vfs_read_retval = 0;
@@ -277,14 +274,11 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                return 0;
 
        if (dev->_isNTSC_ch2) {
-               frame_size =
-                   (line_size ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
-                   FRAME_SIZE_NTSC_Y422;
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
        } else {
-               frame_size =
-                   (line_size ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
        }
 
        frame_offset = (frame_index_temp > 0) ? frame_size : 0;
@@ -318,14 +312,14 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                for (i = 0; i < dev->_lines_count_ch2; i++) {
                        pos = file_offset;
 
-                       vfs_read_retval =
-                           vfs_read(myfile, mybuf, line_size, &pos);
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                       &pos);
 
                        if (vfs_read_retval > 0 && vfs_read_retval == line_size
                            && dev->_data_buf_virt_addr_ch2 != NULL) {
                                memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
                                                frame_offset / 4), mybuf,
-                                      vfs_read_retval);
+                                               vfs_read_retval);
                        }
 
                        file_offset += vfs_read_retval;
@@ -341,8 +335,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                if (i > 0)
                        dev->_frame_count_ch2++;
 
-               dev->_file_status_ch2 =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                filp_close(myfile, NULL);
@@ -353,8 +347,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
 
 static void cx25821_vidups_handler_ch2(struct work_struct *work)
 {
-       struct cx25821_dev *dev =
-           container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _irq_work_entry_ch2);
 
        if (!dev) {
                pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
@@ -362,18 +356,16 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work)
                return;
        }
 
-       cx25821_get_frame_ch2(dev,
-                            dev->channels[dev->
-                              _channel2_upstream_select].sram_channels);
+       cx25821_get_frame_ch2(dev, dev->channels[dev->
+                       _channel2_upstream_select].sram_channels);
 }
 
 int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int i = 0, j = 0;
-       int line_size =
-           (dev->_pixel_format_ch2 ==
-            PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
        ssize_t vfs_read_retval = 0;
        char mybuf[line_size];
        loff_t pos;
@@ -410,16 +402,16 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                        for (i = 0; i < dev->_lines_count_ch2; i++) {
                                pos = offset;
 
-                               vfs_read_retval =
-                                   vfs_read(myfile, mybuf, line_size, &pos);
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
 
-                               if (vfs_read_retval > 0
-                                   && vfs_read_retval == line_size
-                                   && dev->_data_buf_virt_addr_ch2 != NULL) {
+                               if (vfs_read_retval > 0 &&
+                                   vfs_read_retval == line_size &&
+                                   dev->_data_buf_virt_addr_ch2 != NULL) {
                                        memcpy((void *)(dev->
                                                        _data_buf_virt_addr_ch2
                                                        + offset / 4), mybuf,
-                                              vfs_read_retval);
+                                                       vfs_read_retval);
                                }
 
                                offset += vfs_read_retval;
@@ -438,8 +430,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                                break;
                }
 
-               dev->_file_status_ch2 =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                myfile->f_pos = 0;
@@ -463,9 +455,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
                                    dev->_dma_phys_addr_ch2);
        }
 
-       dev->_dma_virt_addr_ch2 =
-           pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
-                                &dma_addr);
+       dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+                       dev->upstream_riscbuf_size_ch2, &dma_addr);
        dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
        dev->_dma_phys_start_addr_ch2 = dma_addr;
        dev->_dma_phys_addr_ch2 = dma_addr;
@@ -485,9 +476,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
                                    dev->_data_buf_phys_addr_ch2);
        }
        /* For Video Data buffer allocation */
-       dev->_data_buf_virt_addr_ch2 =
-           pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2,
-                                &data_dma_addr);
+       dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+                       dev->upstream_databuf_size_ch2, &data_dma_addr);
        dev->_data_buf_phys_addr_ch2 = data_dma_addr;
        dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
 
@@ -563,8 +553,8 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
                                else
                                        line_size_in_bytes = Y422_LINE_SZ;
                                risc_phys_jump_addr =
-                                   dev->_dma_phys_start_addr_ch2 +
-                                   odd_risc_prog_size;
+                                       dev->_dma_phys_start_addr_ch2 +
+                                       odd_risc_prog_size;
 
                                rp = cx25821_update_riscprogram_ch2(dev,
                                                dev->_dma_virt_start_addr_ch2,
@@ -612,11 +602,9 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
        vid_status = cx_read(sram_ch->int_stat);
 
        /* Only deal with our interrupt */
-       if (vid_status) {
-               handled =
-                   cx25821_video_upstream_irq_ch2(dev, channel_num,
-                                                  vid_status);
-       }
+       if (vid_status)
+               handled = cx25821_video_upstream_irq_ch2(dev, channel_num,
+                               vid_status);
 
        if (handled < 0)
                cx25821_stop_upstream_video_ch2(dev);
@@ -691,8 +679,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
        tmp = cx_read(sram_ch->int_msk);
        cx_write(sram_ch->int_msk, tmp |= _intr_msk);
 
-       err =
-           request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
                        IRQF_SHARED, dev->name, dev);
        if (err < 0) {
                pr_err("%s: can't get upstream IRQ %d\n",
@@ -752,45 +739,38 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
        dev->_file_status_ch2 = RESET_STATUS;
        dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
        dev->_pixel_format_ch2 = pixel_format;
-       dev->_line_size_ch2 =
-           (dev->_pixel_format_ch2 ==
-            PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+       dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
        data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
-       risc_buffer_size =
-           dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+       risc_buffer_size = dev->_isNTSC_ch2 ?
+               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
 
        if (dev->input_filename_ch2) {
                str_length = strlen(dev->input_filename_ch2);
-               dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
+                                            str_length + 1, GFP_KERNEL);
 
                if (!dev->_filename_ch2)
                        goto error;
-
-               memcpy(dev->_filename_ch2, dev->input_filename_ch2,
-                      str_length + 1);
        } else {
                str_length = strlen(dev->_defaultname_ch2);
-               dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
+                                            str_length + 1, GFP_KERNEL);
 
                if (!dev->_filename_ch2)
                        goto error;
-
-               memcpy(dev->_filename_ch2, dev->_defaultname_ch2,
-                      str_length + 1);
        }
 
        /* Default if filename is empty string */
        if (strcmp(dev->input_filename_ch2, "") == 0) {
                if (dev->_isNTSC_ch2) {
-                       dev->_filename_ch2 =
-                           (dev->_pixel_format_ch2 ==
-                            PIXEL_FRMT_411) ? "/root/vid411.yuv" :
-                           "/root/vidtest.yuv";
+                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+                               PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+                               "/root/vidtest.yuv";
                } else {
-                       dev->_filename_ch2 =
-                           (dev->_pixel_format_ch2 ==
-                            PIXEL_FRMT_411) ? "/root/pal411.yuv" :
-                           "/root/pal422.yuv";
+                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+                               PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+                               "/root/pal422.yuv";
                }
        }
 
index c0b80068f468b9d62e9d967f92dc96b261491791..21e7d657f049b21daa20d7ab6ef620304946dd4b 100644 (file)
@@ -136,7 +136,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
 {
        unsigned int line, i;
        struct sram_channel *sram_ch =
-          dev->channels[dev->_channel_upstream_select].sram_channels;
+               dev->channels[dev->_channel_upstream_select].sram_channels;
        int dist_betwn_starts = bpl * 2;
 
        /* sync instruction */
@@ -194,15 +194,12 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
        if (dev->_isNTSC) {
                odd_num_lines = singlefield_lines + 1;
                risc_program_size = FRAME1_VID_PROG_SIZE;
-               frame_size =
-                   (bpl ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
-                   FRAME_SIZE_NTSC_Y422;
+               frame_size = (bpl == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
        } else {
                risc_program_size = PAL_VID_PROG_SIZE;
-               frame_size =
-                   (bpl ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+               frame_size = (bpl == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
        }
 
        /* Virtual address of Risc buffer program */
@@ -214,13 +211,9 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
                if (UNSET != top_offset) {
                        fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
                        rp = cx25821_risc_field_upstream(dev, rp,
-                                                        dev->
-                                                        _data_buf_phys_addr +
-                                                        databuf_offset,
-                                                        top_offset, 0, bpl,
-                                                        odd_num_lines,
-                                                        fifo_enable,
-                                                        ODD_FIELD);
+                                       dev->_data_buf_phys_addr +
+                                       databuf_offset, top_offset, 0, bpl,
+                                       odd_num_lines, fifo_enable, ODD_FIELD);
                }
 
                fifo_enable = FIFO_DISABLE;
@@ -234,8 +227,8 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
 
                if (frame == 0) {
                        risc_flag = RISC_CNT_RESET;
-                       risc_phys_jump_addr =
-                           dev->_dma_phys_start_addr + risc_program_size;
+                       risc_phys_jump_addr = dev->_dma_phys_start_addr +
+                               risc_program_size;
                } else {
                        risc_phys_jump_addr = dev->_dma_phys_start_addr;
                        risc_flag = RISC_CNT_INC;
@@ -255,7 +248,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
 void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
 {
        struct sram_channel *sram_ch =
-          dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
        u32 tmp = 0;
 
        if (!dev->_is_running) {
@@ -312,9 +305,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
        struct file *myfile;
        int frame_index_temp = dev->_frame_index;
        int i = 0;
-       int line_size =
-           (dev->_pixel_format ==
-            PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
        int frame_size = 0;
        int frame_offset = 0;
        ssize_t vfs_read_retval = 0;
@@ -326,16 +318,12 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
        if (dev->_file_status == END_OF_FILE)
                return 0;
 
-       if (dev->_isNTSC) {
-               frame_size =
-                   (line_size ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
-                   FRAME_SIZE_NTSC_Y422;
-       } else {
-               frame_size =
-                   (line_size ==
-                    Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
-       }
+       if (dev->_isNTSC)
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+       else
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
 
        frame_offset = (frame_index_temp > 0) ? frame_size : 0;
        file_offset = dev->_frame_count * frame_size;
@@ -369,8 +357,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                for (i = 0; i < dev->_lines_count; i++) {
                        pos = file_offset;
 
-                       vfs_read_retval =
-                           vfs_read(myfile, mybuf, line_size, &pos);
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                       &pos);
 
                        if (vfs_read_retval > 0 && vfs_read_retval == line_size
                            && dev->_data_buf_virt_addr != NULL) {
@@ -392,8 +380,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                if (i > 0)
                        dev->_frame_count++;
 
-               dev->_file_status =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_file_status = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                filp_close(myfile, NULL);
@@ -404,8 +392,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
 
 static void cx25821_vidups_handler(struct work_struct *work)
 {
-       struct cx25821_dev *dev =
-           container_of(work, struct cx25821_dev, _irq_work_entry);
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _irq_work_entry);
 
        if (!dev) {
                pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
@@ -413,18 +401,16 @@ static void cx25821_vidups_handler(struct work_struct *work)
                return;
        }
 
-       cx25821_get_frame(dev,
-                        dev->channels[dev->_channel_upstream_select].
-                                              sram_channels);
+       cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
+                       sram_channels);
 }
 
 int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
 {
        struct file *myfile;
        int i = 0, j = 0;
-       int line_size =
-           (dev->_pixel_format ==
-            PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
        ssize_t vfs_read_retval = 0;
        char mybuf[line_size];
        loff_t pos;
@@ -461,8 +447,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                        for (i = 0; i < dev->_lines_count; i++) {
                                pos = offset;
 
-                               vfs_read_retval =
-                                   vfs_read(myfile, mybuf, line_size, &pos);
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
 
                                if (vfs_read_retval > 0
                                    && vfs_read_retval == line_size
@@ -489,8 +475,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
                                break;
                }
 
-               dev->_file_status =
-                   (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+               dev->_file_status = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
 
                set_fs(old_fs);
                myfile->f_pos = 0;
@@ -507,14 +493,12 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
        dma_addr_t dma_addr;
        dma_addr_t data_dma_addr;
 
-       if (dev->_dma_virt_addr != NULL) {
+       if (dev->_dma_virt_addr != NULL)
                pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
-                                   dev->_dma_virt_addr, dev->_dma_phys_addr);
-       }
+                               dev->_dma_virt_addr, dev->_dma_phys_addr);
 
-       dev->_dma_virt_addr =
-           pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size,
-                                &dma_addr);
+       dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->upstream_riscbuf_size, &dma_addr);
        dev->_dma_virt_start_addr = dev->_dma_virt_addr;
        dev->_dma_phys_start_addr = dma_addr;
        dev->_dma_phys_addr = dma_addr;
@@ -528,15 +512,13 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
        /* Clear memory at address */
        memset(dev->_dma_virt_addr, 0, dev->_risc_size);
 
-       if (dev->_data_buf_virt_addr != NULL) {
+       if (dev->_data_buf_virt_addr != NULL)
                pci_free_consistent(dev->pci, dev->upstream_databuf_size,
-                                   dev->_data_buf_virt_addr,
-                                   dev->_data_buf_phys_addr);
-       }
+                               dev->_data_buf_virt_addr,
+                               dev->_data_buf_phys_addr);
        /* For Video Data buffer allocation */
-       dev->_data_buf_virt_addr =
-           pci_alloc_consistent(dev->pci, dev->upstream_databuf_size,
-                                &data_dma_addr);
+       dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->upstream_databuf_size, &data_dma_addr);
        dev->_data_buf_phys_addr = data_dma_addr;
        dev->_data_buf_size = dev->upstream_databuf_size;
 
@@ -553,9 +535,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
                return ret;
 
        /* Create RISC programs */
-       ret =
-           cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
-                                        dev->_lines_count);
+       ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+                       dev->_lines_count);
        if (ret < 0) {
                pr_info("Failed creating Video Upstream Risc programs!\n");
                goto error;
@@ -672,10 +653,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
        vid_status = cx_read(sram_ch->int_stat);
 
        /* Only deal with our interrupt */
-       if (vid_status) {
-               handled =
-                   cx25821_video_upstream_irq(dev, channel_num, vid_status);
-       }
+       if (vid_status)
+               handled = cx25821_video_upstream_irq(dev, channel_num,
+                               vid_status);
 
        if (handled < 0)
                cx25821_stop_upstream_video_ch1(dev);
@@ -747,8 +727,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
        tmp = cx_read(sram_ch->int_msk);
        cx_write(sram_ch->int_msk, tmp |= _intr_msk);
 
-       err =
-           request_irq(dev->pci->irq, cx25821_upstream_irq,
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq,
                        IRQF_SHARED, dev->name, dev);
        if (err < 0) {
                pr_err("%s: can't get upstream IRQ %d\n",
@@ -807,43 +786,38 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        dev->_file_status = RESET_STATUS;
        dev->_lines_count = dev->_isNTSC ? 480 : 576;
        dev->_pixel_format = pixel_format;
-       dev->_line_size =
-           (dev->_pixel_format ==
-            PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
        data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
-       risc_buffer_size =
-           dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+       risc_buffer_size = dev->_isNTSC ?
+               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
 
        if (dev->input_filename) {
                str_length = strlen(dev->input_filename);
-               dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_filename = kmemdup(dev->input_filename, str_length + 1,
+                                        GFP_KERNEL);
 
                if (!dev->_filename)
                        goto error;
-
-               memcpy(dev->_filename, dev->input_filename, str_length + 1);
        } else {
                str_length = strlen(dev->_defaultname);
-               dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+               dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
+                                        GFP_KERNEL);
 
                if (!dev->_filename)
                        goto error;
-
-               memcpy(dev->_filename, dev->_defaultname, str_length + 1);
        }
 
        /* Default if filename is empty string */
        if (strcmp(dev->input_filename, "") == 0) {
                if (dev->_isNTSC) {
                        dev->_filename =
-                           (dev->_pixel_format ==
-                            PIXEL_FRMT_411) ? "/root/vid411.yuv" :
-                           "/root/vidtest.yuv";
+                               (dev->_pixel_format == PIXEL_FRMT_411) ?
+                               "/root/vid411.yuv" : "/root/vidtest.yuv";
                } else {
                        dev->_filename =
-                           (dev->_pixel_format ==
-                            PIXEL_FRMT_411) ? "/root/pal411.yuv" :
-                           "/root/pal422.yuv";
+                               (dev->_pixel_format == PIXEL_FRMT_411) ?
+                               "/root/pal411.yuv" : "/root/pal422.yuv";
                }
        }
 
@@ -852,13 +826,11 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
        dev->_file_status = RESET_STATUS;
        dev->_lines_count = dev->_isNTSC ? 480 : 576;
        dev->_pixel_format = pixel_format;
-       dev->_line_size =
-           (dev->_pixel_format ==
-            PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
 
-       retval =
-           cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size,
-                                               0);
+       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+                       dev->_line_size, 0);
 
        /* setup fifo + format */
        cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
index 4d6907cda75b8a0c2405e88bb569ba6953b64d81..ffd8bc79c02e61358a48d89eab07f2d35cad450c 100644 (file)
@@ -118,12 +118,12 @@ void cx25821_dump_video_queue(struct cx25821_dev *dev,
 
        if (!list_empty(&q->active)) {
                list_for_each(item, &q->active)
-                   buf = list_entry(item, struct cx25821_buffer, vb.queue);
+                       buf = list_entry(item, struct cx25821_buffer, vb.queue);
        }
 
        if (!list_empty(&q->queued)) {
                list_for_each(item, &q->queued)
-                   buf = list_entry(item, struct cx25821_buffer, vb.queue);
+                       buf = list_entry(item, struct cx25821_buffer, vb.queue);
        }
 
 }
@@ -140,8 +140,8 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
                        break;
                }
 
-               buf =
-                   list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
 
                /* count comes from the hw and it is 16bit wide --
                 * this trick handles wrap-arounds correctly for
@@ -318,8 +318,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
        struct list_head *item;
 
        if (!list_empty(&q->active)) {
-               buf =
-                   list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
 
                cx25821_start_video_dma(dev, q, buf, channel);
 
@@ -337,8 +337,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
                if (list_empty(&q->queued))
                        return 0;
 
-               buf =
-                   list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+               buf = list_entry(q->queued.next, struct cx25821_buffer,
+                               vb.queue);
 
                if (NULL == prev) {
                        list_move_tail(&buf->vb.queue, &q->active);
@@ -375,8 +375,8 @@ void cx25821_vid_timeout(unsigned long data)
 
        spin_lock_irqsave(&dev->slock, flags);
        while (!list_empty(&q->active)) {
-               buf =
-                   list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
                list_del(&buf->vb.queue);
 
                buf->vb.state = VIDEOBUF_ERROR;
@@ -484,8 +484,7 @@ int cx25821_video_register(struct cx25821_dev *dev)
                cx25821_init_controls(dev, i);
 
                cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
-                               dev->channels[i].sram_channels->dma_ctl,
-                               0x11, 0);
+                       dev->channels[i].sram_channels->dma_ctl, 0x11, 0);
 
                dev->channels[i].sram_channels = &cx25821_sram_channels[i];
                dev->channels[i].video_dev = NULL;
@@ -499,15 +498,14 @@ int cx25821_video_register(struct cx25821_dev *dev)
                dev->channels[i].timeout_data.dev = dev;
                dev->channels[i].timeout_data.channel =
                        &cx25821_sram_channels[i];
-               dev->channels[i].vidq.timeout.function =
-                       cx25821_vid_timeout;
+               dev->channels[i].vidq.timeout.function = cx25821_vid_timeout;
                dev->channels[i].vidq.timeout.data =
                        (unsigned long)&dev->channels[i].timeout_data;
                init_timer(&dev->channels[i].vidq.timeout);
 
                /* register v4l devices */
-               dev->channels[i].video_dev = cx25821_vdev_init(dev,
-                               dev->pci, &cx25821_video_device, "video");
+               dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci,
+                               &cx25821_video_device, "video");
 
                err = video_register_device(dev->channels[i].video_dev,
                                VFL_TYPE_GRABBER, video_nr[dev->nr]);
@@ -528,7 +526,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
 #endif
        mutex_unlock(&dev->lock);
 
-
        return 0;
 
 fail_unreg:
@@ -558,7 +555,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
        struct cx25821_fh *fh = q->priv_data;
        struct cx25821_dev *dev = fh->dev;
        struct cx25821_buffer *buf =
-           container_of(vb, struct cx25821_buffer, vb);
+               container_of(vb, struct cx25821_buffer, vb);
        int rc, init_buffer = 0;
        u32 line0_offset, line1_offset;
        struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
@@ -617,14 +614,13 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                        if (channel_opened >= 0 && channel_opened <= 7) {
                                if (dev->channels[channel_opened]
                                                .use_cif_resolution) {
-                                       if (dev->tvnorm & V4L2_STD_PAL_BG
-                                           || dev->tvnorm & V4L2_STD_PAL_DK)
+                                       if (dev->tvnorm & V4L2_STD_PAL_BG ||
+                                           dev->tvnorm & V4L2_STD_PAL_DK)
                                                bpl_local = 352 << 1;
                                        else
-                                               bpl_local =
-                                                dev->channels[channel_opened].
-                                                cif_width <<
-                                                1;
+                                               bpl_local = dev->channels[
+                                                       channel_opened].
+                                                       cif_width << 1;
                                }
                        }
                }
@@ -685,7 +681,7 @@ void cx25821_buffer_release(struct videobuf_queue *q,
                            struct videobuf_buffer *vb)
 {
        struct cx25821_buffer *buf =
-           container_of(vb, struct cx25821_buffer, vb);
+               container_of(vb, struct cx25821_buffer, vb);
 
        cx25821_free_buffer(q, buf);
 }
@@ -723,7 +719,7 @@ int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
 static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 {
        struct cx25821_buffer *buf =
-          container_of(vb, struct cx25821_buffer, vb);
+               container_of(vb, struct cx25821_buffer, vb);
        struct cx25821_buffer *prev;
        struct cx25821_fh *fh = vq->priv_data;
        struct cx25821_dev *dev = fh->dev;
@@ -814,7 +810,7 @@ static int video_open(struct file *file)
 
                for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
                        if (h->channels[i].video_dev &&
-                          h->channels[i].video_dev->minor == minor) {
+                           h->channels[i].video_dev->minor == minor) {
                                dev = h;
                                ch_id = i;
                                type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -848,11 +844,10 @@ static int video_open(struct file *file)
 
        v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
 
-       videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
-                             &dev->pci->dev, &dev->slock,
-                             V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                             V4L2_FIELD_INTERLACED,
-                             sizeof(struct cx25821_buffer), fh, NULL);
+       videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev,
+                       &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                       V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
+                       fh, NULL);
 
        dprintk(1, "post videobuf_queue_init()\n");
        mutex_unlock(&cx25821_devlist_mutex);
@@ -1168,8 +1163,8 @@ int cx25821_vidioc_querycap(struct file *file, void *priv,
        strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
        sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
        cap->version = CX25821_VERSION_CODE;
-       cap->capabilities =
-           V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING;
        if (UNSET != dev->tuner_type)
                cap->capabilities |= V4L2_CAP_TUNER;
        return 0;
@@ -1454,38 +1449,38 @@ static const struct v4l2_queryctrl no_ctl = {
 static struct v4l2_queryctrl cx25821_ctls[] = {
        /* --- video --- */
        {
-        .id = V4L2_CID_BRIGHTNESS,
-        .name = "Brightness",
-        .minimum = 0,
-        .maximum = 10000,
-        .step = 1,
-        .default_value = 6200,
-        .type = V4L2_CTRL_TYPE_INTEGER,
-        }, {
-            .id = V4L2_CID_CONTRAST,
-            .name = "Contrast",
-            .minimum = 0,
-            .maximum = 10000,
-            .step = 1,
-            .default_value = 5000,
-            .type = V4L2_CTRL_TYPE_INTEGER,
-            }, {
-                .id = V4L2_CID_SATURATION,
-                .name = "Saturation",
-                .minimum = 0,
-                .maximum = 10000,
-                .step = 1,
-                .default_value = 5000,
-                .type = V4L2_CTRL_TYPE_INTEGER,
-                }, {
-                    .id = V4L2_CID_HUE,
-                    .name = "Hue",
-                    .minimum = 0,
-                    .maximum = 10000,
-                    .step = 1,
-                    .default_value = 5000,
-                    .type = V4L2_CTRL_TYPE_INTEGER,
-                    }
+               .id = V4L2_CID_BRIGHTNESS,
+               .name = "Brightness",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 6200,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_CONTRAST,
+               .name = "Contrast",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_SATURATION,
+               .name = "Saturation",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_HUE,
+               .name = "Hue",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }
 };
 static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
 
@@ -1623,7 +1618,8 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv,
 
        if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
-       cropcap->bounds.top = cropcap->bounds.left = 0;
+       cropcap->bounds.top = 0;
+       cropcap->bounds.left = 0;
        cropcap->bounds.width = 720;
        cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
        cropcap->pixelaspect.numerator =
@@ -1829,8 +1825,11 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
        struct downstream_user_struct *data_from_user;
        int command;
        int width = 720;
-       int selected_channel = 0, pix_format = 0, i = 0;
-       int cif_enable = 0, cif_width = 0;
+       int selected_channel = 0;
+       int pix_format = 0;
+       int i = 0;
+       int cif_enable = 0;
+       int cif_width = 0;
        u32 value = 0;
 
        data_from_user = (struct downstream_user_struct *)arg;
@@ -1895,8 +1894,8 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
                }
 
                if (selected_channel <= 7 && selected_channel >= 0) {
-                       dev->channels[selected_channel].
-                               use_cif_resolution = cif_enable;
+                       dev->channels[selected_channel].use_cif_resolution =
+                               cif_enable;
                        dev->channels[selected_channel].cif_width = width;
                } else {
                        for (i = 0; i < VID_CHANNEL_NUM; i++) {
@@ -1932,9 +1931,9 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
 static long cx25821_video_ioctl(struct file *file,
                                unsigned int cmd, unsigned long arg)
 {
-       int  ret = 0;
+       int ret = 0;
 
-       struct cx25821_fh  *fh  = file->private_data;
+       struct cx25821_fh *fh = file->private_data;
 
        /* check to see if it's the video upstream */
        if (fh->channel_id == SRAM_CH09) {
index 2d2d00932823a09dae7cb07595d1cb42b4613e28..b9aa801b00a7b29c01c45334dd14d6c7c61bb978 100644 (file)
@@ -67,7 +67,7 @@
 #define MAX_CAMERAS             16
 
 /* Max number of inputs by card */
-#define MAX_CX25821_INPUT 8
+#define MAX_CX25821_INPUT     8
 #define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
 #define RESOURCE_VIDEO0       1
 #define RESOURCE_VIDEO1       2
@@ -85,7 +85,7 @@
 
 #define BUFFER_TIMEOUT     (HZ)        /* 0.5 seconds */
 
-#define UNKNOWN_BOARD       0
+#define UNKNOWN_BOARD        0
 #define CX25821_BOARD        1
 
 /* Currently supported by the driver */
index 005f11093642711cc854dce2decb70760ee08fdd..34b96c7cfd620007b88a7082166413c284ac7a0e 100644 (file)
@@ -480,7 +480,6 @@ void cx25840_audio_set_path(struct i2c_client *client)
 
 static void set_volume(struct i2c_client *client, int volume)
 {
-       struct cx25840_state *state = to_state(i2c_get_clientdata(client));
        int vol;
 
        /* Convert the volume to msp3400 values (0-127) */
@@ -496,14 +495,7 @@ static void set_volume(struct i2c_client *client, int volume)
        }
 
        /* PATH1_VOLUME */
-       if (is_cx2388x(state)) {
-               /* for cx23885 volume doesn't work,
-                * the calculation always results in
-                * e4 regardless.
-                */
-               cx25840_write(client, 0x8d4, volume);
-       } else
-               cx25840_write(client, 0x8d4, 228 - (vol * 2));
+       cx25840_write(client, 0x8d4, 228 - (vol * 2));
 }
 
 static void set_balance(struct i2c_client *client, int balance)
index cd9976408ab33050498633ee5c8c3e87a8d2f24c..05247d4c340a6c7f74e9a19f21f931571fc675d7 100644 (file)
@@ -18,6 +18,9 @@
  * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
  * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
  *
+ * CX23888 DIF support for the HVR1850
+ * Copyright (C) 2011 Steven Toth <stoth@kernellabs.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
@@ -40,6 +43,7 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/math64.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/cx25840.h>
@@ -80,6 +84,7 @@ MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
 
 
 /* ----------------------------------------------------------------------- */
+static void cx23885_std_setup(struct i2c_client *client);
 
 int cx25840_write(struct i2c_client *client, u16 addr, u8 value)
 {
@@ -498,8 +503,13 @@ static void cx23885_initialize(struct i2c_client *client)
                 * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz
                 * 572.73 MHz before post divide
                 */
-               cx25840_write4(client, 0x11c, 0x00e8ba26);
-               cx25840_write4(client, 0x118, 0x0000040b);
+               /* HVR1850 or 50MHz xtal */
+               cx25840_write(client, 0x2, 0x71);
+               cx25840_write4(client, 0x11c, 0x01d1744c);
+               cx25840_write4(client, 0x118, 0x00000416);
+               cx25840_write4(client, 0x404, 0x0010253e);
+               cx25840_write4(client, 0x42c, 0x42600000);
+               cx25840_write4(client, 0x44c, 0x161f1000);
                break;
        case V4L2_IDENT_CX23887_AV:
                /*
@@ -533,8 +543,18 @@ static void cx23885_initialize(struct i2c_client *client)
         * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz
         * 432.0 MHz before post divide
         */
-       cx25840_write4(client, 0x10c, 0x002be2c9);
-       cx25840_write4(client, 0x108, 0x0000040f);
+
+       /* HVR1850 */
+       switch (state->id) {
+       case V4L2_IDENT_CX23888_AV:
+               /* 888/HVR1250 specific */
+               cx25840_write4(client, 0x10c, 0x13333333);
+               cx25840_write4(client, 0x108, 0x00000515);
+               break;
+       default:
+               cx25840_write4(client, 0x10c, 0x002be2c9);
+               cx25840_write4(client, 0x108, 0x0000040f);
+       }
 
        /* Luma */
        cx25840_write4(client, 0x414, 0x00107d12);
@@ -556,8 +576,9 @@ static void cx23885_initialize(struct i2c_client *client)
                 * 368.64 MHz before post divide
                 * 122.88 MHz / 0xa = 12.288 MHz
                 */
-               cx25840_write4(client, 0x114, 0x00bedfa4);
-               cx25840_write4(client, 0x110, 0x000a0307);
+               /* HVR1850  or 50MHz xtal */
+               cx25840_write4(client, 0x114, 0x017dbf48);
+               cx25840_write4(client, 0x110, 0x000a030e);
                break;
        case V4L2_IDENT_CX23887_AV:
                /*
@@ -617,7 +638,10 @@ static void cx23885_initialize(struct i2c_client *client)
        finish_wait(&state->fw_wait, &wait);
        destroy_workqueue(q);
 
-       cx25840_std_setup(client);
+       /* Call the cx23885 specific std setup func, we no longer rely on
+        * the generic cx24840 func.
+        */
+       cx23885_std_setup(client);
 
        /* (re)set input */
        set_input(client, state->vid_input, state->aud_input);
@@ -631,6 +655,37 @@ static void cx23885_initialize(struct i2c_client *client)
        /* Disable and clear audio interrupts - we don't use them */
        cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
        cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
+
+       /* CC raw enable */
+       /*  - VIP 1.1 control codes - 10bit, blue field enable.
+        *  - enable raw data during vertical blanking.
+        *  - enable ancillary Data insertion for 656 or VIP.
+        */
+       cx25840_write4(client, 0x404, 0x0010253e);
+
+       /* CC on  - Undocumented Register */
+       cx25840_write(client, 0x42f, 0x66);
+
+       /* HVR-1250 / HVR1850 DIF related */
+       /* Power everything up */
+       cx25840_write4(client, 0x130, 0x0);
+
+       /* Undocumented */
+       cx25840_write4(client, 0x478, 0x6628021F);
+
+       /* AFE_CLK_OUT_CTRL - Select the clock output source as output */
+       cx25840_write4(client, 0x144, 0x5);
+
+       /* I2C_OUT_CTL - I2S output configuration as
+        * Master, Sony, Left justified, left sample on WS=1
+        */
+       cx25840_write4(client, 0x918, 0x1a0);
+
+       /* AFE_DIAG_CTRL1 */
+       cx25840_write4(client, 0x134, 0x000a1800);
+
+       /* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */
+       cx25840_write4(client, 0x13c, 0x00310000);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -945,9 +1000,14 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                           vid_input <= CX25840_COMPOSITE8);
        u8 is_component = (vid_input & CX25840_COMPONENT_ON) ==
                        CX25840_COMPONENT_ON;
+       u8 is_dif = (vid_input & CX25840_DIF_ON) ==
+                       CX25840_DIF_ON;
+       u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) ==
+                       CX25840_SVIDEO_ON;
        int luma = vid_input & 0xf0;
        int chroma = vid_input & 0xf00;
        u8 reg;
+       u32 val;
 
        v4l_dbg(1, cx25840_debug, client,
                "decoder set video input %d, audio input %d\n",
@@ -1012,6 +1072,66 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
        else
                cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
 
+       if (is_cx2388x(state)) {
+
+               /* Enable or disable the DIF for tuner use */
+               if (is_dif) {
+                       cx25840_and_or(client, 0x102, ~0x80, 0x80);
+
+                       /* Set of defaults for NTSC and PAL */
+                       cx25840_write4(client, 0x31c, 0xc2262600);
+                       cx25840_write4(client, 0x320, 0xc2262600);
+
+                       /* 18271 IF - Nobody else yet uses a different
+                        * tuner with the DIF, so these are reasonable
+                        * assumptions (HVR1250 and HVR1850 specific).
+                        */
+                       cx25840_write4(client, 0x318, 0xda262600);
+                       cx25840_write4(client, 0x33c, 0x2a24c800);
+                       cx25840_write4(client, 0x104, 0x0704dd00);
+               } else {
+                       cx25840_write4(client, 0x300, 0x015c28f5);
+
+                       cx25840_and_or(client, 0x102, ~0x80, 0);
+                       cx25840_write4(client, 0x340, 0xdf7df83);
+                       cx25840_write4(client, 0x104, 0x0704dd80);
+                       cx25840_write4(client, 0x314, 0x22400600);
+                       cx25840_write4(client, 0x318, 0x40002600);
+                       cx25840_write4(client, 0x324, 0x40002600);
+                       cx25840_write4(client, 0x32c, 0x0250e620);
+                       cx25840_write4(client, 0x39c, 0x01FF0B00);
+
+                       cx25840_write4(client, 0x410, 0xffff0dbf);
+                       cx25840_write4(client, 0x414, 0x00137d03);
+                       cx25840_write4(client, 0x418, 0x01008080);
+                       cx25840_write4(client, 0x41c, 0x00000000);
+                       cx25840_write4(client, 0x420, 0x001c3e0f);
+                       cx25840_write4(client, 0x42c, 0x42600000);
+                       cx25840_write4(client, 0x430, 0x0000039b);
+                       cx25840_write4(client, 0x438, 0x00000000);
+
+                       cx25840_write4(client, 0x440, 0xF8E3E824);
+                       cx25840_write4(client, 0x444, 0x401040dc);
+                       cx25840_write4(client, 0x448, 0xcd3f02a0);
+                       cx25840_write4(client, 0x44c, 0x161f1000);
+                       cx25840_write4(client, 0x450, 0x00000802);
+
+                       cx25840_write4(client, 0x91c, 0x01000000);
+                       cx25840_write4(client, 0x8e0, 0x03063870);
+                       cx25840_write4(client, 0x8d4, 0x7FFF0024);
+                       cx25840_write4(client, 0x8d0, 0x00063073);
+
+                       cx25840_write4(client, 0x8c8, 0x00010000);
+                       cx25840_write4(client, 0x8cc, 0x00080023);
+
+                       /* DIF BYPASS */
+                       cx25840_write4(client, 0x33c, 0x2a04c800);
+               }
+
+               /* Reset the DIF */
+               cx25840_write4(client, 0x398, 0);
+       }
+
        if (!is_cx2388x(state) && !is_cx231xx(state)) {
                /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
                cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
@@ -1036,6 +1156,33 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                                cx25840_and_or(client, 0x102, ~0x2, 0);
                        }
                }
+
+               /* cx23885 / SVIDEO */
+               if (is_cx2388x(state) && is_svideo) {
+#define AFE_CTRL  (0x104)
+#define MODE_CTRL (0x400)
+                       cx25840_and_or(client, 0x102, ~0x2, 0x2);
+
+                       val = cx25840_read4(client, MODE_CTRL);
+                       val &= 0xFFFFF9FF;
+
+                       /* YC */
+                       val |= 0x00000200;
+                       val &= ~0x2000;
+                       cx25840_write4(client, MODE_CTRL, val);
+
+                       val = cx25840_read4(client, AFE_CTRL);
+
+                       /* Chroma in select */
+                       val |= 0x00001000;
+                       val &= 0xfffffe7f;
+                       /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8).
+                        * This sets them to use video rather than audio.
+                        * Only one of the two will be in use.
+                        */
+                       cx25840_write4(client, AFE_CTRL, val);
+               } else
+                       cx25840_and_or(client, 0x102, ~0x2, 0);
        }
 
        state->vid_input = vid_input;
@@ -1086,6 +1233,23 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                cx25840_write4(client, 0x8d0, 0x1f063870);
        }
 
+       if (is_cx2388x(state)) {
+               /* HVR1850 */
+               /* AUD_IO_CTRL - I2S Input, Parallel1*/
+               /*  - Channel 1 src - Parallel1 (Merlin out) */
+               /*  - Channel 2 src - Parallel2 (Merlin out) */
+               /*  - Channel 3 src - Parallel3 (Merlin AC97 out) */
+               /*  - I2S source and dir - Merlin, output */
+               cx25840_write4(client, 0x124, 0x100);
+
+               if (!is_dif) {
+                       /* Stop microcontroller if we don't need it
+                        * to avoid audio popping on svideo/composite use.
+                        */
+                       cx25840_and_or(client, 0x803, ~0x10, 0x00);
+               }
+       }
+
        return 0;
 }
 
@@ -1134,7 +1298,10 @@ static int set_v4lstd(struct i2c_client *client)
        }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
        cx25840_and_or(client, 0x403, ~0x3, pal_m);
-       cx25840_std_setup(client);
+       if (is_cx2388x(state))
+               cx23885_std_setup(client);
+       else
+               cx25840_std_setup(client);
        if (!is_cx2583x(state))
                input_change(client);
        return 0;
@@ -1539,6 +1706,56 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
+/* Query the current detected video format */
+static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       v4l2_std_id stds[] = {
+               /* 0000 */ V4L2_STD_UNKNOWN,
+
+               /* 0001 */ V4L2_STD_NTSC_M,
+               /* 0010 */ V4L2_STD_NTSC_M_JP,
+               /* 0011 */ V4L2_STD_NTSC_443,
+               /* 0100 */ V4L2_STD_PAL,
+               /* 0101 */ V4L2_STD_PAL_M,
+               /* 0110 */ V4L2_STD_PAL_N,
+               /* 0111 */ V4L2_STD_PAL_Nc,
+               /* 1000 */ V4L2_STD_PAL_60,
+
+               /* 1001 */ V4L2_STD_UNKNOWN,
+               /* 1010 */ V4L2_STD_UNKNOWN,
+               /* 1001 */ V4L2_STD_UNKNOWN,
+               /* 1010 */ V4L2_STD_UNKNOWN,
+               /* 1011 */ V4L2_STD_UNKNOWN,
+               /* 1110 */ V4L2_STD_UNKNOWN,
+               /* 1111 */ V4L2_STD_UNKNOWN
+       };
+
+       u32 fmt = (cx25840_read4(client, 0x40c) >> 8) & 0xf;
+       *std = stds[ fmt ];
+
+       v4l_dbg(1, cx25840_debug, client, "g_std fmt = %x, v4l2_std_id = 0x%x\n",
+               fmt, (unsigned int)stds[ fmt ]);
+
+       return 0;
+}
+
+static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       /* A limited function that checks for signal status and returns
+        * the state.
+        */
+
+       /* Check for status of Horizontal lock (SRC lock isn't reliable) */
+       if ((cx25840_read4(client, 0x40c) & 0x00010000) == 0)
+               *status |= V4L2_IN_ST_NO_SIGNAL;
+
+       return 0;
+}
+
 static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 {
        struct cx25840_state *state = to_state(sd);
@@ -1565,6 +1782,9 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd,
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
+       if (is_cx2388x(state))
+               cx23885_std_setup(client);
+
        return set_input(client, input, state->aud_input);
 }
 
@@ -1574,6 +1794,8 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
+       if (is_cx2388x(state))
+               cx23885_std_setup(client);
        return set_input(client, state->vid_input, input);
 }
 
@@ -1786,6 +2008,3007 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
 
 /* ----------------------------------------------------------------------- */
 
+#define DIF_PLL_FREQ_WORD      (0x300)
+#define DIF_BPF_COEFF01                (0x348)
+#define DIF_BPF_COEFF23                (0x34c)
+#define DIF_BPF_COEFF45                (0x350)
+#define DIF_BPF_COEFF67                (0x354)
+#define DIF_BPF_COEFF89                (0x358)
+#define DIF_BPF_COEFF1011      (0x35c)
+#define DIF_BPF_COEFF1213      (0x360)
+#define DIF_BPF_COEFF1415      (0x364)
+#define DIF_BPF_COEFF1617      (0x368)
+#define DIF_BPF_COEFF1819      (0x36c)
+#define DIF_BPF_COEFF2021      (0x370)
+#define DIF_BPF_COEFF2223      (0x374)
+#define DIF_BPF_COEFF2425      (0x378)
+#define DIF_BPF_COEFF2627      (0x37c)
+#define DIF_BPF_COEFF2829      (0x380)
+#define DIF_BPF_COEFF3031      (0x384)
+#define DIF_BPF_COEFF3233      (0x388)
+#define DIF_BPF_COEFF3435      (0x38c)
+#define DIF_BPF_COEFF36                (0x390)
+
+void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
+{
+       u64 pll_freq;
+       u32 pll_freq_word;
+
+       v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz);
+
+       /* Assuming TV */
+       /* Calculate the PLL frequency word based on the adjusted ifHz */
+        pll_freq = div_u64((u64)ifHz * 268435456, 50000000);
+        pll_freq_word = (u32)pll_freq;
+
+        cx25840_write4(client, DIF_PLL_FREQ_WORD,  pll_freq_word);
+
+       /* Round down to the nearest 100KHz */
+       ifHz = (ifHz / 100000) * 100000;
+
+       if (ifHz < 3000000)
+               ifHz = 3000000;
+
+       if (ifHz > 16000000)
+               ifHz = 16000000;
+
+       v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz);
+
+       switch (ifHz) {
+       case 3000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00220032);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00370026);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff91);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0efe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fdcc);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe0afedb);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440224);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0434060c);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738074e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x06090361);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99fb39);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef3b6);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21af2a5);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf573fa33);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034067d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bfb0fb9);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000e);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00200038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x004c004f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x002fffdf);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff5cfeb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dfd92);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7ffe03);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36010a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x03410575);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x072607d2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x071804d5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134fcb7);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff451);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223f22e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4a7f94b);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xff6405e8);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bae0fa4);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00000008);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0036);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0056006d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00670030);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffbdff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46fd8d);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd25fd4f);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35ffe0);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0224049f);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9080e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x07ef0627);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9fe45);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f513);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250f1d2);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3ecf869);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930552);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b5f0f8f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0001);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000f002c);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0054007d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0093007c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0024ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6fdbb);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd03fcca);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51feb9);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x00eb0392);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270802);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08880750);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x044dffdb);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf5f8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0f193);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf342f78f);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc404b9);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b0e0f78);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff9);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0002001b);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0046007d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad00ba);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00870000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe1a);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1bfc7e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fda4);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xffa5025c);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x054507ad);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08dd0847);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80172);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef6ff);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313f170);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2abf6bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6041f);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0abc0f61);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff3);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff50006);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x002f006c);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b200e3);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00dc007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9fea0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd6bfc71);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fcb1);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe65010b);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x042d0713);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ec0906);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020302);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff823);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7f16a);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf228f5f5);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2a0384);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a670f4a);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7ffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9fff1);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0010004d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a100f2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x011a00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053ff44);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdedfca2);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fbef);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd39ffae);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x02ea0638);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08b50987);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230483);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f960);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45bf180);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1b8f537);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb6102e7);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a110f32);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffdd);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00024);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x007c00e5);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013a014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e6fff8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe98fd0f);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fb67);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc32fe54);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x01880525);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x083909c7);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x091505ee);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7fab3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52df1b4);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf15df484);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9b0249);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x09ba0f19);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 3900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff0);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffcf);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1fff6);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x004800be);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01390184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x016300ac);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff5efdb1);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb23);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb5cfd0d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x001703e4);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x077b09c4);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d2073c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251fc18);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61cf203);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf118f3dc);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d801aa);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x09600eff);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffefff4);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffca);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x000b0082);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01170198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10152);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0030fe7b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb24);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfac3fbe9);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5027f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0683097f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a560867);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2fd89);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723f26f);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0e8f341);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919010a);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x09060ee5);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fffb);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8ffca);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffa4);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffcd0036);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d70184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f601dc);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ffff60);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb6d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6efaf5);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd410103);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x055708f9);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e0969);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543ff02);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842f2f5);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cef2b2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85e006b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x08aa0ecb);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00050003);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff3ffd3);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaff8b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ffe5);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0080014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe023f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ba0050);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fbf8);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa62fa3b);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9ff7e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x04010836);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa90a3d);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f007f);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf975f395);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cbf231);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ffcb);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x084c0eaf);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000a);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0000ffe4);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff81);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff96);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x001c00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70271);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0254013b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fcbd);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa9ff9c5);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbfdfe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x028c073b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a750adf);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e101fa);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab8f44e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0ddf1be);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ff2b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x07ed0e94);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000efff8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff87);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff54);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffb5007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01860270);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c00210);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fdb2);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb22f997);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2fc90);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0102060f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a050b4c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902036e);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0af51e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf106f15a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64efe8b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x078d0e77);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0019000e);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff9e);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff25);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff560000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112023b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f702c0);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfec8);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbe5f9b3);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947fb41);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xff7004b9);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a0b81);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a0004d8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd65f603);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf144f104);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aafdec);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x072b0e5a);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00060012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00200022);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ffc1);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff09ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x008601d7);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f50340);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fff0);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcddfa19);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa1e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfde30343);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x08790b7f);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50631);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec7f6fc);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf198f0bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50dfd4e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x06c90e3d);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00220030);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffed);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff87ff15);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed6ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffed014c);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b90386);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110119);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfdfefac4);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6f92f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc6701b7);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x07670b44);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0776);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x002df807);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf200f086);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477fcb1);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x06650e1e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0009);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003f001b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffbcff36);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec2feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff5600a5);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0248038d);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00232);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xff39fbab);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4f87f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb060020);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x062a0ad2);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf908a3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0192f922);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf27df05e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8fc14);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x06000e00);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 4900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0002);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00160037);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00510046);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xfff9ff6d);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed0fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefff0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01aa0356);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413032b);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x007ffcc5);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cf812);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9cefe87);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c90a2c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4309b4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f3fa4a);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf30ef046);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361fb7a);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x059b0de0);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000a002d);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00570067);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0037ffb5);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfefffe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62ff3d);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ec02e3);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x043503f6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x01befe05);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa27f7ee);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8c6fcf8);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x034c0954);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0aa4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x044cfb7e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3b1f03f);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2fae1);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x05340dc0);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff4);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffd001e);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0051007b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x006e0006);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff48fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfe9a);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x001d023e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130488);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x02e6ff5b);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1ef812);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7f7fb7f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bc084e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430b72);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x059afcba);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf467f046);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cfa4a);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x04cd0da0);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff00009);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003f007f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00980056);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffa5feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe15);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff4b0170);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b004d7);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x03e800b9);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc48f87f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf768fa23);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022071f);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90c1b);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x06dafdfd);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf52df05e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef9b5);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x04640d7f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6fff3);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00250072);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00af009c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x000cff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13fdb8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe870089);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104e1);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04b8020f);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd98f92f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf71df8f0);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe8805ce);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0c9c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0808ff44);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf603f086);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af922);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x03fb0d5e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe0);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00050056);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b000d1);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0071ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53fd8c);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfddfff99);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104a3);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x054a034d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xff01fa1e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf717f7ed);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf50461);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50cf4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0921008d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf6e7f0bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff891);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x03920d3b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffffff3);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffd1);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5002f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x009c00ed);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00cb0000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfebafd94);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd61feb0);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d0422);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05970464);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0074fb41);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf759f721);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb7502de);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000d21);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a2201d4);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7d9f104);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf804);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x03280d19);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fffa);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3ffc9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc90002);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x007500ef);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x010e007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3dfdcf);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd16fddd);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440365);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x059b0548);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3fc90);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7dff691);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0f014d);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020d23);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0318);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8d7f15a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f779);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x02bd0cf6);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00060001);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffecffc9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffd4);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x004000d5);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013600f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd3fe39);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd04fd31);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff360277);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x055605ef);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x033efdfe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8a5f642);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbffb6);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10cfb);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50456);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9dff1be);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f6f2);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x02520cd2);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080009);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff8ffd2);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffac);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x000200a3);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013c014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x006dfec9);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2bfcb7);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe350165);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04cb0651);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477ff7e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9a5f635);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1fe20);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0ca8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c81058b);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfaf0f231);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f66d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x01e60cae);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 5900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000e);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0005ffe1);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffacff90);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5005f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01210184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fcff72);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd8afc77);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51003f);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04020669);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830103);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfad7f66b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8fc93);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430c2b);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d06b5);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfc08f2b2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af5ec);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x017b0c89);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0012fff5);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaff82);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff8e000f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e80198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750028);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe18fc75);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99ff15);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x03050636);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0656027f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc32f6e2);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614fb17);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20b87);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d7707d2);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfd26f341);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf56f);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x010f0c64);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00050012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001c000b);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff84);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ffbe);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00960184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd00da);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeccfcb2);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fdf9);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x01e005bc);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e703e4);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfdabf798);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f9b3);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510abd);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf08df);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfe48f3dc);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f4f6);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x00a20c3e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0002000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0021001f);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff97);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff74);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0034014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa0179);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff97fd2a);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fcfa);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x00a304fe);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310525);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xff37f886);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf86e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c709d0);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de209db);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xff6df484);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf481);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0x00360c18);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe000a);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0021002f);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ffb8);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff3b);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffcc00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa01fa);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0069fdd4);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fc26);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xff5d0407);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310638);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x00c9f9a8);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf74e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xff3908c3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de20ac3);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0093f537);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf410);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xffca0bf2);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb0003);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001c0037);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x002fffe2);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ff17);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff6a007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd0251);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0134fea5);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb8b);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe2002e0);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e70713);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0255faf5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f658);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0799);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf0b96);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x01b8f5f5);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f3a3);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xff5e0bca);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00120037);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00460010);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff8eff0f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff180000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750276);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01e8ff8d);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb31);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcfb0198);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x065607ad);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x03cefc64);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614f592);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0656);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d770c52);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x02daf6bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf33b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfef10ba3);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff5);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0005002f);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0054003c);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5ff22);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedfff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fc0267);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0276007e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb1c);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbfe003e);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830802);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0529fdec);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8f4fe);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd04ff);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d0cf6);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x03f8f78f);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af2d7);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe850b7b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff80020);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00560060);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0002ff4e);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec4ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x006d0225);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02d50166);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb4e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb35fee1);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477080e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x065bff82);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1f4a0);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610397);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c810d80);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0510f869);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f278);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe1a0b52);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffaffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffec000c);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0078);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0040ff8e);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecafeb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd301b6);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fc0235);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fbc5);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaaafd90);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x033e07d2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x075b011b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbf47a);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f0224);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50def);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0621f94b);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f21e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfdae0b29);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 6900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3fff6);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0037007f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0075ffdc);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef2fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3d0122);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02ea02dd);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fc79);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa65fc5d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3074e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x082102ad);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0ff48c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe00a9);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0e43);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0729fa33);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f1c9);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfd430b00);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0001fff3);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe2);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x001b0076);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x009c002d);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff35fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfeba0076);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x029f0352);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfd60);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa69fb53);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x00740688);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08a7042d);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb75f4d6);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600ff2d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a220e7a);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0827fb22);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf17a);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfcd80ad6);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff9);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffd2);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb005e);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b0007a);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8ffe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53ffc1);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0221038c);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fe6e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfab6fa80);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xff010587);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e90590);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf5f556);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfdb3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x09210e95);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0919fc15);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff12f);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc6e0aab);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00070000);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6ffc9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0039);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00af00b8);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfff4feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01790388);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311ff92);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb48f9ed);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd980453);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e306cd);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe88f60a);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fc40);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x08080e93);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x09fdfd0c);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af0ea);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc050a81);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080008);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff0ffc9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1000d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x009800e2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x005bff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe74);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00b50345);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000bc);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc18f9a1);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc4802f9);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x089807dc);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022f6f0);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fada);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x06da0e74);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ad3fe06);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef0ab);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb9c0a55);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000e);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffdffd0);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffdf);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x006e00f2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00b8ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfdf8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xffe302c8);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x041301dc);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd1af99e);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1e0183);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x080908b5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bcf801);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf985);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x059a0e38);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b99ff03);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cf071);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb330a2a);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00070011);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000affdf);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffa9ffb5);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x003700e6);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01010000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62fda8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff140219);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x043502e1);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe42f9e6);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa270000);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x073a0953);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x034cf939);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a4f845);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x044c0de1);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c4f0000);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2f03c);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfacc09fe);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00040012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0016fff3);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffafff95);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xfff900c0);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0130007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefd89);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe560146);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x041303bc);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xff81fa76);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cfe7d);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x063209b1);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c9fa93);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf71e);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f30d6e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cf200fd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361f00e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa6509d1);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00010010);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0008);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ff84);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffbc0084);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013e00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff56fd9f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdb8005c);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00460);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x00c7fb45);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4fd07);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x04fa09ce);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x062afc07);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407f614);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x01920ce0);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d8301fa);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8efe5);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa0009a4);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd000b);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001d);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff82);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff870039);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x012a014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffedfde7);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd47ff6b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104c6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0202fc4c);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6fbad);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x039909a7);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0767fd8e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482f52b);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x002d0c39);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e0002f4);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477efc2);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf99b0977);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 7900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa0004);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0020002d);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff91);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ffe8);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f70184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0086fe5c);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0bfe85);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104e5);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0323fd7d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa79);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x021d093f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0879ff22);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bf465);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec70b79);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e6803eb);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50defa5);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf937094a);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffd);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00190036);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x001bffaf);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff99);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00aa0198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112fef3);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd09fdb9);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04be);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x041bfecc);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947f978);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x00900897);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a00b9);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f3c5);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd650aa3);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ebc04de);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aaef8e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf8d5091c);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff6);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000e0038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ffd7);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff56);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x004b0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0186ffa1);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd40fd16);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440452);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04de0029);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2f8b2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfefe07b5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a05024d);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef34d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0a09b8);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0efa05cd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64eef7d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf87308ed);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00000031);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0005);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff27);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffe4014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70057);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdacfca6);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3603a7);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05610184);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbf82e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd74069f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a7503d6);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff2ff);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab808b9);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f2306b5);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ef72);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf81308bf);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff30022);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00560032);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8000f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe0106);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe46fc71);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3502c7);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x059e02ce);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9f7f2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfbff055b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa9054c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f2db);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf97507aa);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f350797);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ef6d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7b40890);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8000f);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00540058);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffcdff14);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff29007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f6019e);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff01fc7c);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5101bf);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x059203f6);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd41f7fe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfaa903f3);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e06a9);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf2e2);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842068b);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f320871);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85eef6e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7560860);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fff2);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1fff9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00460073);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x000bff34);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee90000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10215);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xffd0fcc5);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99009d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x053d04f1);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5f853);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf97d0270);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a5607e4);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef314);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723055f);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f180943);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919ef75);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6fa0830);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff8);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe4);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x002f007f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0048ff6b);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec7ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0163025f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00a2fd47);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff73);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04a405b2);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0017f8ed);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf88500dc);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d208f9);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff370);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61c0429);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ee80a0b);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d8ef82);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6a00800);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0007ffff);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffd4);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0010007a);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x007cffb2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec6ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e60277);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0168fdf9);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fe50);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x03ce0631);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0188f9c8);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7c7ff43);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x091509e3);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f3f6);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52d02ea);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ea30ac9);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9bef95);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf64607d0);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00090007);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9ffca);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00065);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a10003);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee6feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053025b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0213fed0);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fd46);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x02c70668);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x02eafadb);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf74bfdae);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230a9c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f4a3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45b01a6);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e480b7c);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb61efae);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf5ef079f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 8900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000d);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff5ffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10043);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b20053);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff24fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9020c);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0295ffbb);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fc64);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x019b0654);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x042dfc1c);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf714fc2a);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020b21);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f575);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7005e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0dd80c24);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2aefcd);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf599076e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00060011);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0002ffcf);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffba0018);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad009a);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff79fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff260192);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e500ab);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fbb6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x005b05f7);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545fd81);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf723fabf);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80b70);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f669);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313ff15);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d550cbf);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6eff2);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544073d);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00030012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000fffdd);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffea);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x009300cf);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdcfe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea600f7);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fd0190);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb46);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xff150554);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0627fefd);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf778f978);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x044d0b87);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f77d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0fdcf);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbe0d4e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc4f01d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2070b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00000010);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001afff0);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffbf);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x006700ed);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe460047);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02db0258);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb1b);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddc0473);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c90082);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf811f85e);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c90b66);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff8ad);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250fc8d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c140dcf);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe93f04d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a106d9);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc000c);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00200006);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff9c);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x002f00ef);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a4ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dff92);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x028102f7);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb37);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbf035e);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07260202);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e8f778);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x01340b0d);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f9f4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223fb51);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b590e42);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xff64f083);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf45206a7);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90005);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001a);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff86);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xfff000d7);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fee5);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f60362);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb99);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbcc0222);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07380370);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f7f6cc);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xff990a7e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902fb50);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21afa1f);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8d0ea6);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034f0bf);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4050675);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffe);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001e002b);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff81);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffb400a5);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe50);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01460390);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfc3a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb1000ce);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x070104bf);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb37f65f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe0009bc);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00fcbb);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f8f8);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b20efc);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105f101);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3ba0642);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff7);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00150036);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff8c);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff810061);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013d007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe71fddf);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x007c0380);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fd13);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa94ff70);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x068005e2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9bf633);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc7308ca);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5fe30);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf274f7e0);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c90f43);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d4f147);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371060f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fff1);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00090038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffa7);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff5e0012);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013200f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee3fd9b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaa0331);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fe15);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa60fe18);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bd06d1);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1bf64a);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafa07ae);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7effab);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d5f6d7);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d30f7a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a3f194);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf32905dc);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffb0032);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003fffcd);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effc1);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6efd8a);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfedd02aa);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0ff34);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa74fcd7);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bf0781);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaaf6a3);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99e066b);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90128);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf359f5e1);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d20fa2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0370f1e5);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e405a8);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 9900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffef0024);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0051fffa);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff54ff77);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00be0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0006fdad);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe2701f3);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413005e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad1fbba);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x039007ee);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x013bf73d);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868050a);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4302a1);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fdf4fe);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c70fba);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x043bf23c);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a10575);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fff1);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe50011);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00570027);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff70ff3c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00620198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x009efe01);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95011a);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350183);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb71fad0);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x023c0812);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c3f811);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75e0390);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0411);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c1f432);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b30fc1);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0503f297);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2610541);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0006fff7);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdffffc);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00510050);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff9dff18);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffc0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0128fe80);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32002e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130292);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4dfa21);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d107ee);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0435f91c);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6850205);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430573);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a1f37d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x03990fba);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c7f2f8);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222050d);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffe);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdfffe7);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003f006e);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffd6ff0f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0197ff1f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd05ff3e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0037c);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd59f9b7);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5d0781);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0585fa56);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4006f);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf906c4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69df2e0);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x02790fa2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0688f35d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e604d8);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00090005);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4ffd6);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0025007e);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0014ff20);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3c00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e1ffd0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd12fe5c);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110433);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88f996);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf106d1);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aafbb7);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57efed8);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e07ff);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b0f25e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x01560f7a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0745f3c7);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1ac04a4);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000c);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffedffcb);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0005007d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0050ff4c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ff0086);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd58fd97);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104ad);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xffcaf9c0);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc9905e2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x079afd35);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf555fd46);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50920);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d9f1f6);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x00310f43);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fdf435);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174046f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00050011);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffaffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5006b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0082ff8c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f00130);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd2fcfc);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04e3);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x010efa32);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb6404bf);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x084efec5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569fbc2);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000a23);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa15f1ab);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0b0efc);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b0f4a7);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13f043a);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00020012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0007ffcd);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9004c);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a4ffd9);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b401c1);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe76fc97);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404d2);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0245fae8);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5f0370);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1005f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bcfa52);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020b04);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb60f17b);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde70ea6);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x095df51e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10c0405);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0011);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0014ffdb);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40023);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2002a);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedbff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150022d);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff38fc6f);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36047b);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x035efbda);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9940202);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ee01f5);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf649f8fe);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10bc2);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb6f169);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc60e42);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a04f599);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0db03d0);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb000d);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001dffed);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaafff5);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00aa0077);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00ce026b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x000afc85);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3503e3);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x044cfcfb);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90c0082);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5037f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf710f7cc);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0c59);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe16f173);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaa0dcf);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa5f617);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0ad039b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 10900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90006);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00210003);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffc8);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x008e00b6);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff63fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x003a0275);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00dafcda);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd510313);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0501fe40);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cbfefd);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x087604f0);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80af6c2);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430cc8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7af19a);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa940d4e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3ff699);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0810365);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffff);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00210018);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffa3);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x006000e1);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc4fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0024b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x019afd66);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc990216);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0575ff99);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4fd81);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d40640);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf932f5e6);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20d0d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x00dff1de);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9860cbf);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd1f71e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058032f);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff8);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001b0029);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff8a);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x002600f2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x002cfe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0f01f0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x023bfe20);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc1700fa);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a200f7);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf927fc1c);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f40765);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa82f53b);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510d27);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0243f23d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8810c24);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5cf7a7);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf03102fa);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00110035);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff81);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffe700e7);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x008ffeb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94016d);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b0fefb);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3ffd1);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05850249);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c1fadb);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x05de0858);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf2f4c4);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c70d17);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a0f2b8);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7870b7c);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdff833);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00d02c4);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00040038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ff88);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffac00c2);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e2ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe3900cb);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f1ffe9);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3feaa);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05210381);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9cf9c8);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x04990912);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7af484);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xff390cdb);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f4f34d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69a0ac9);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5af8c1);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefec028e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0000ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff60033);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x002fff9f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff7b0087);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x011eff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe080018);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f900d8);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fd96);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x04790490);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbadf8ed);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x032f098e);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xff10f47d);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0c75);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x063cf3fc);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5ba0a0b);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dccf952);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcd0258);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff1);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffea0026);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0046ffc3);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff5a003c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04ff63);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c801b8);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fca6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397056a);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcecf853);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x01ad09c9);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x00acf4ad);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0be7);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0773f4c2);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e90943);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35f9e6);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb10221);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff6);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe20014);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0054ffee);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effeb);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2efebb);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260027a);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fbe6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x02870605);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4af7fe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x001d09c1);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0243f515);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd0b32);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0897f59e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4280871);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e95fa7c);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef9701eb);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffd);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffff);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0056001d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff57ff9c);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x011300f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe82fe2e);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ca0310);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb62);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155065a);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xffbaf7f2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8c0977);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x03cef5b2);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610a58);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a5f68f);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3790797);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eebfb14);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef8001b5);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080004);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0047);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff75ff58);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef9fdc8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111036f);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb21);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x00120665);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x012df82e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd0708ec);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542f682);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f095c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9af792);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2db06b5);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f38fbad);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6c017e);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 11900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000b);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe7ffd8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00370068);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffa4ff28);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00790184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87fd91);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00430392);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb26);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfece0626);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294f8b2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb990825);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0698f77f);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe0842);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b73f8a7);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf25105cd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7bfc48);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5a0148);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00050010);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff2ffcc);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x001b007b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffdfff10);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00140198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0020fd8e);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff710375);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb73);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9a059f);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e0f978);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4e0726);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c8f8a7);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600070c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2ff9c9);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1db04de);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4fce5);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4b0111);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00010012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffffffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb007e);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x001dff14);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffad0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b7fdbe);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9031b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fc01);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc8504d6);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0504fa79);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf93005f6);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x08caf9f2);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52b05c0);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccbfaf9);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf17903eb);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3fd83);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3f00db);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe0011);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000cffcc);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0071);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0058ff32);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4f014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x013cfe1f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfb028a);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fcc9);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9d03d6);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f4fbad);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848049d);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0999fb5b);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf4820461);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d46fc32);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12d02f4);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x1007fe21);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3600a4);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0017ffd9);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc10055);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0088ff68);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0400f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a6fea7);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7501cc);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fdc0);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaef02a8);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a7fd07);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79d0326);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a31fcda);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf40702f3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9ffd72);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f601fa);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x1021fec0);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2f006d);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80007);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001fffeb);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaf002d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a8ffb0);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e9ff4c);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2000ee);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fed8);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82015c);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0715fe7d);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7340198);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8dfe69);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bd017c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd5feb8);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d500fd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x1031ff60);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2b0037);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff70000);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00220000);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffa90000);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b30000);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec20000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x02000000);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd030000);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350000);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa5e0000);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x073b0000);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7110000);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aac0000);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a40000);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de70000);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0c90000);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x10360000);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef290000);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff9);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001f0015);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffd3);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a80050);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e900b4);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd20ff12);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130128);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82fea4);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x07150183);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf734fe68);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8d0197);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdfe84);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd50148);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d5ff03);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x103100a0);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2bffc9);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00170027);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ffab);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00880098);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff04ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a60159);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd75fe34);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00240);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaeffd58);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a702f9);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79dfcda);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a310326);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fd0d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9f028e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f6fe06);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x10210140);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2fff93);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000c0034);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff8f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x005800ce);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4ffeb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x013c01e1);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfbfd76);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110337);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9dfc2a);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f40453);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848fb63);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x099904a5);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fb9f);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d4603ce);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12dfd0c);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x100701df);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef36ff5c);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 12900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0001ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffff0038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff82);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x001d00ec);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffadfe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b70242);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9fce5);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x024103ff);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc85fb2a);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05040587);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf930fa0a);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x08ca060e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfa40);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccb0507);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf179fc15);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3027d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3fff25);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff0);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff20034);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x001bff85);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffdf00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0014fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00200272);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff71fc8b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d048d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9afa61);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e00688);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4ef8da);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c80759);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f8f4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2f0637);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1dbfb22);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4031b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4bfeef);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff5);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe70028);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ff98);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffa400d8);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0079fe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87026f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0043fc6e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404da);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfecef9da);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294074e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb99f7db);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x06980881);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef7be);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b730759);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf251fa33);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7b03b8);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5afeb8);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffc);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe00017);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x004cffb9);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff7500a8);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef90238);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111fc91);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604df);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0012f99b);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x012d07d2);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd07f714);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542097e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff6a4);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9a086e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2dbf94b);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f380453);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6cfe82);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080003);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffde0001);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0056ffe3);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff570064);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0113ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe8201d2);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01cafcf0);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35049e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155f9a6);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xffba080e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8cf689);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x03ce0a4e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f5a8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a50971);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf379f869);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eeb04ec);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef80fe4b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000a);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe2ffec);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00540012);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e0015);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2e0145);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260fd86);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51041a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0287f9fb);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4a0802);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x001df63f);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x02430aeb);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf4ce);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x08970a62);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf428f78f);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e950584);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xef97fe15);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffeaffda);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0046003d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff5affc4);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04009d);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c8fe48);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99035a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397fa96);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcec07ad);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x01adf637);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x00ac0b53);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef419);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x07730b3e);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e9f6bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35061a);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb1fddf);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00000012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfff6ffcd);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x002f0061);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff7bff79);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x011e007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe08ffe8);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f9ff28);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17026a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0479fb70);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbad0713);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x032ff672);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xff100b83);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff38b);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x063c0c04);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5baf5f5);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dcc06ae);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcdfda8);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0004ffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00100078);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffacff3e);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e200f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe39ff35);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f10017);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd30156);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0521fc7f);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9c0638);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0499f6ee);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7a0b7c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f325);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f40cb3);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69af537);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5a073f);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xefecfd72);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0011ffcb);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0007f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffe7ff19);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x008f014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94fe93);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b00105);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3002f);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x0585fdb7);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c10525);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x05def7a8);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf20b3c);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f2e9);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a00d48);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf787f484);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdf07cd);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00dfd3c);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 13900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80008);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001bffd7);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10076);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0026ff0e);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x002c0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0ffe10);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x023b01e0);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff06);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a2ff09);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf92703e4);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f4f89b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa820ac5);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f2d9);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x02430dc3);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf881f3dc);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5c0859);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf031fd06);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80001);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0021ffe8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffba005d);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0060ff1f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc40198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0fdb5);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x019a029a);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fdea);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x05750067);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4027f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d4f9c0);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf9320a1a);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f2f3);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0x00df0e22);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xf986f341);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd108e2);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058fcd1);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0021fffd);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0038);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x008eff4a);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff630184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x003afd8b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x00da0326);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fced);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x050101c0);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cb0103);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x0876fb10);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80a093e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f338);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7a0e66);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa94f2b2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3f0967);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf081fc9b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff3);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001d0013);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa000b);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00aaff89);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00cefd95);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x000a037b);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fc1d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x044c0305);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90cff7e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5fc81);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7100834);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff3a7);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe160e8d);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaaf231);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa509e9);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0adfc65);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00140025);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffdd);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2ffd6);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedb00f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150fdd3);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xff380391);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb85);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x035e0426);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xf994fdfe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08eefe0b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6490702);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f43e);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb60e97);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc6f1be);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a040a67);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0dbfc30);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0002ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00070033);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ffb4);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00a40027);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b4fe3f);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe760369);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb2e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x02450518);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5ffc90);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1ffa1);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bc05ae);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902f4fc);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb600e85);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde7f15a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x095d0ae2);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10cfbfb);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0005ffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffa0038);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff95);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00820074);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f0fed0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd20304);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb1d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x010e05ce);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb64fb41);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x084e013b);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569043e);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00f5dd);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa150e55);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0bf104);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b00b59);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13ffbc6);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fff4);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffed0035);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff83);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x005000b4);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6ff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ffff7a);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd580269);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fb53);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xffca0640);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc99fa1e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x079a02cb);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55502ba);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5f6e0);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d90e0a);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0031f0bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fd0bcb);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174fb91);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0009fffb);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4002a);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ff82);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x001400e0);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3cff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e10030);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1201a4);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fbcd);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88066a);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf1f92f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aa0449);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57e0128);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7ef801);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b00da2);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0156f086);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x07450c39);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1acfb5c);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00080002);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0019);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003fff92);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffd600f1);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x019700e1);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0500c2);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fc84);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd590649);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5df87f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x058505aa);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4ff91);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9f93c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69d0d20);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0279f05e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x06880ca3);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e6fb28);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 14900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x00060009);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0004);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0051ffb0);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff9d00e8);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffcfe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x01280180);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32ffd2);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fd6e);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4d05df);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d1f812);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x043506e4);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf685fdfb);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fa8d);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a10c83);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0399f046);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c70d08);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222faf3);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffe5ffef);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x0057ffd9);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff7000c4);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0062fe68);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x009e01ff);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95fee6);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0435fe7d);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb710530);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x023cf7ee);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c307ef);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75efc70);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5cfbef);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c10bce);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b3f03f);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x05030d69);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf261fabf);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15100000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xffefffdc);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00510006);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff540089);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00befe7c);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0x00060253);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe27fe0d);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413ffa2);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad10446);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0390f812);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0x013b08c3);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868faf6);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fd5f);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fd0b02);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c7f046);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x043b0dc4);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a1fa8b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15200000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0012);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0xfffbffce);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x003f0033);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e003f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106feb6);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6e0276);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeddfd56);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000cc);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa740329);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bff87f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaa095d);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99ef995);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9fed8);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3590a1f);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d2f05e);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x03700e1b);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e4fa58);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15300000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9000f);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0009ffc8);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00250059);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff5effee);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0132ff10);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee30265);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaafccf);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x031101eb);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6001e8);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bdf92f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1b09b6);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafaf852);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0055);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d50929);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d3f086);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a30e6c);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf329fa24);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15400000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80009);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0015ffca);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0x00050074);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xff81ff9f);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x013dff82);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe710221);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x007cfc80);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x024102ed);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa940090);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0680fa1e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9b09cd);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc73f736);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad501d0);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2740820);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c9f0bd);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d40eb9);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371f9f1);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15500000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80002);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001effd5);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5007f);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff5b);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2401b0);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0146fc70);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d03c6);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb10ff32);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0701fb41);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb3709a1);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f644);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000345);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2350708);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b2f104);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x01050eff);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3baf9be);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15600000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0022ffe6);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9007a);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff29);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2007e);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01011b);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f6fc9e);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440467);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbccfdde);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738fc90);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f70934);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99f582);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x090204b0);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21a05e1);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8df15a);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0x00340f41);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf405f98b);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15700000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcfff4);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x0020fffa);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40064);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x002fff11);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a400f0);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0d006e);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x0281fd09);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604c9);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbffca2);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0726fdfe);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e80888);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134f4f3);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1060c);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf22304af);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b59f1be);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xff640f7d);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf452f959);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15800000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0000fff0);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0010);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa0041);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0067ff13);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043014a);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46ffb9);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02dbfda8);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3504e5);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddcfb8d);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9ff7e);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf81107a2);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9f49a);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0753);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2500373);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c14f231);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930fb3);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a1f927);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 15900000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0003ffee);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x000f0023);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0016);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x0093ff31);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdc0184);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6ff09);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fdfe70);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5104ba);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0xff15faac);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270103);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7780688);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x044df479);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430883);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a00231);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbef2b2);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc40fe3);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2f8f5);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+
+       case 16000000:
+               cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+               cx25840_write4(client, DIF_BPF_COEFF23, 0x0006ffef);
+               cx25840_write4(client, DIF_BPF_COEFF45, 0x00020031);
+               cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffe8);
+               cx25840_write4(client, DIF_BPF_COEFF89, 0x00adff66);
+               cx25840_write4(client, DIF_BPF_COEFF1011, 0xff790198);
+               cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe6e);
+               cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e5ff55);
+               cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99044a);
+               cx25840_write4(client, DIF_BPF_COEFF1819, 0x005bfa09);
+               cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545027f);
+               cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7230541);
+               cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b8f490);
+               cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20997);
+               cx25840_write4(client, DIF_BPF_COEFF2829, 0xf31300eb);
+               cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d55f341);
+               cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6100e);
+               cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544f8c3);
+               cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+               break;
+       }
+}
+
+static void cx23885_std_setup(struct i2c_client *client)
+{
+       struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+       v4l2_std_id std = state->std;
+       u32 ifHz;
+
+       cx25840_write4(client, 0x478, 0x6628021F);
+       cx25840_write4(client, 0x400, 0x0);
+       cx25840_write4(client, 0x4b4, 0x20524030);
+       cx25840_write4(client, 0x47c, 0x010a8263);
+
+       if (std & V4L2_STD_NTSC) {
+               v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC",
+                       __func__);
+
+               /* Horiz / vert timing */
+               cx25840_write4(client, 0x428, 0x1e1e601a);
+               cx25840_write4(client, 0x424, 0x5b2d007a);
+
+               /* DIF NTSC */
+               cx25840_write4(client, 0x304, 0x6503bc0c);
+               cx25840_write4(client, 0x308, 0xbd038c85);
+               cx25840_write4(client, 0x30c, 0x1db4640a);
+               cx25840_write4(client, 0x310, 0x00008800);
+               cx25840_write4(client, 0x314, 0x44400400);
+               cx25840_write4(client, 0x32c, 0x0c800800);
+               cx25840_write4(client, 0x330, 0x27000100);
+               cx25840_write4(client, 0x334, 0x1f296e1f);
+               cx25840_write4(client, 0x338, 0x009f50c1);
+               cx25840_write4(client, 0x340, 0x1befbf06);
+               cx25840_write4(client, 0x344, 0x000035e8);
+
+               /* DIF I/F */
+               ifHz = 5400000;
+
+       } else {
+               v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG",
+                       __func__);
+
+               /* Horiz / vert timing */
+               cx25840_write4(client, 0x428, 0x28244024);
+               cx25840_write4(client, 0x424, 0x5d2d0084);
+
+               /* DIF */
+               cx25840_write4(client, 0x304, 0x6503bc0c);
+               cx25840_write4(client, 0x308, 0xbd038c85);
+               cx25840_write4(client, 0x30c, 0x1db4640a);
+               cx25840_write4(client, 0x310, 0x00008800);
+               cx25840_write4(client, 0x314, 0x44400600);
+               cx25840_write4(client, 0x32c, 0x0c800800);
+               cx25840_write4(client, 0x330, 0x27000100);
+               cx25840_write4(client, 0x334, 0x213530ec);
+               cx25840_write4(client, 0x338, 0x00a65ba8);
+               cx25840_write4(client, 0x340, 0x1befbf06);
+               cx25840_write4(client, 0x344, 0x000035e8);
+
+               /* DIF I/F */
+               ifHz = 6000000;
+       }
+
+       cx23885_dif_setup(client, ifHz);
+
+       /* Explicitly ensure the inputs are reconfigured after
+        * a standard change.
+        */
+       set_input(client, state->vid_input, state->aud_input);
+}
+
+/* ----------------------------------------------------------------------- */
+
 static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
        .s_ctrl = cx25840_s_ctrl,
 };
@@ -1801,6 +5024,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = {
        .queryctrl = v4l2_subdev_queryctrl,
        .querymenu = v4l2_subdev_querymenu,
        .s_std = cx25840_s_std,
+       .g_std = cx25840_g_std,
        .reset = cx25840_reset,
        .load_fw = cx25840_load_fw,
        .s_io_pin_config = common_s_io_pin_config,
@@ -1828,6 +5052,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
        .s_routing = cx25840_s_video_routing,
        .s_mbus_fmt = cx25840_s_mbus_fmt,
        .s_stream = cx25840_s_stream,
+       .g_input_status = cx25840_g_input_status,
 };
 
 static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
index 5c42abdf422f35fe47a77c711f47adea3e8c26fa..3598dc087b0880fd5214f8f96b36b377678b1a00 100644 (file)
@@ -70,11 +70,6 @@ config VIDEO_CX88_DVB
          To compile this driver as a module, choose M here: the
          module will be called cx88-dvb.
 
-config VIDEO_CX88_MPEG
-       tristate
-       depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
-       default y
-
 config VIDEO_CX88_VP3054
        tristate "VP-3054 Secondary I2C Bus Support"
        default m
@@ -84,3 +79,8 @@ config VIDEO_CX88_VP3054
          Conexant 2388x chip and the MT352 demodulator,
          which also require support for the VP-3054
          Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
+config VIDEO_CX88_MPEG
+       tristate
+       depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
+       default y
index 0d719faafd8aeb32e0a260d080622355d8fafa68..62c7ad050f9bb0b067a963405ddda6e8cbcd1838 100644 (file)
@@ -1306,7 +1306,7 @@ static const struct cx88_board cx88_boards[] = {
        },
        [CX88_BOARD_WINFAST_DTV2000H_J] = {
                .name           = "WinFast DTV2000 H rev. J",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
@@ -1643,6 +1643,78 @@ static const struct cx88_board cx88_boards[] = {
                        .gpio3  = 0x0000,
                },
        },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = {
+               .name           = "Leadtek TV2000 XP Global (SC4100)",
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,        /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
+               .name           = "Leadtek TV2000 XP Global (XC4100)",
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6040,       /* pin 14 = 1, pin 13 = 0 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,        /* pin 2 = 0 */
+                       .gpio1  = 0x6000,        /* pin 14 = 1, pin 13 = 0 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               },
+       },
        [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
                .name           = "PowerColor RA330",   /* Long names may confuse LIRC. */
                .tuner_type     = TUNER_XC2028,
@@ -2718,6 +2790,21 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x107d,
                .subdevice = 0x6618,
                .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               /* TV2000 XP Global [107d:6618] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6619,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               /* WinFast TV2000 XP Global with XC4000 tuner */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f36,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
+       }, {
+               /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f43,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
        }, {
                .subvendor = 0xb034,
                .subdevice = 0x3034,
@@ -3075,6 +3162,8 @@ static int cx88_xc4000_tuner_callback(struct cx88_core *core,
        switch (core->boardnr) {
        case CX88_BOARD_WINFAST_DTV1800H_XC4000:
        case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
                return cx88_xc4000_winfast2000h_plus_callback(core,
                                                              command, arg);
        }
@@ -3232,6 +3321,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
                cx_set(MO_GP0_IO, 0x00001010);
                break;
 
+       case CX88_BOARD_WINFAST_DTV2000H_J:
        case CX88_BOARD_HAUPPAUGE_HVR3000:
        case CX88_BOARD_HAUPPAUGE_HVR4000:
                /* Init GPIO */
@@ -3250,6 +3340,8 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
 
        case CX88_BOARD_WINFAST_DTV1800H_XC4000:
        case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
                cx88_xc4000_winfast2000h_plus_callback(core,
                                                       XC4000_TUNER_RESET, 0);
                break;
index cf3d33ab541b8ee190dcd7fbdaefc6130895a002..003937cd72f553e80bceecdcb9a0befe8986630a 100644 (file)
@@ -815,9 +815,9 @@ static const u8 samsung_smt_7020_inittab[] = {
 };
 
 
-static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe,
-       struct dvb_frontend_parameters *params)
+static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct cx8802_dev *dev = fe->dvb->priv;
        u8 buf[4];
        u32 div;
@@ -827,14 +827,14 @@ static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe,
                .buf = buf,
                .len = sizeof(buf) };
 
-       div = params->frequency / 125;
+       div = c->frequency / 125;
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x84;  /* 0xC4 */
        buf[3] = 0x00;
 
-       if (params->frequency < 1500000)
+       if (c->frequency < 1500000)
                buf[3] |= 0x10;
 
        if (fe->ops.i2c_gate_ctrl)
@@ -954,6 +954,7 @@ static int dvb_register(struct cx8802_dev *dev)
        struct cx88_core *core = dev->core;
        struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
        int mfe_shared = 0; /* bus not shared by default */
+       int res = -EINVAL;
 
        if (0 != core->i2c_rc) {
                printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
@@ -999,7 +1000,6 @@ static int dvb_register(struct cx8802_dev *dev)
                }
                break;
        case CX88_BOARD_WINFAST_DTV2000H:
-       case CX88_BOARD_WINFAST_DTV2000H_J:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
        case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -1013,6 +1013,17 @@ static int dvb_register(struct cx8802_dev *dev)
                                goto frontend_detach;
                }
                break;
+       case CX88_BOARD_WINFAST_DTV2000H_J:
+               fe0->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216MEX_MK3))
+                               goto frontend_detach;
+               }
+               break;
        case CX88_BOARD_HAUPPAUGE_HVR3000:
                /* MFE frontend 1 */
                mfe_shared = 1;
@@ -1566,13 +1577,16 @@ static int dvb_register(struct cx8802_dev *dev)
        call_all(core, core, s_power, 0);
 
        /* register everything */
-       return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-                                        &dev->pci->dev, adapter_nr, mfe_shared, NULL);
+       res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+               &dev->pci->dev, adapter_nr, mfe_shared, NULL);
+       if (res)
+               goto frontend_detach;
+       return res;
 
 frontend_detach:
        core->gate_ctrl = NULL;
        videobuf_dvb_dealloc_frontends(&dev->frontends);
-       return -EINVAL;
+       return res;
 }
 
 /* ----------------------------------------------------------- */
index a1fe0abb6e43051c49d36b964e5a3069809219c7..de0f1af74e415bc516cd9b12fd97b4b34a8cc45e 100644 (file)
@@ -132,7 +132,7 @@ static void do_i2c_scan(const char *name, struct i2c_client *c)
        }
 }
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
 {
        /* Prevents usage of invalid delay values */
index e614201b5ed33b5994ec4528ece3574e7f90919d..ebf448c48ca3335ce6cdb0a0091270fcdb96bd57 100644 (file)
@@ -103,6 +103,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
        case CX88_BOARD_WINFAST_DTV1800H_XC4000:
        case CX88_BOARD_WINFAST_DTV2000H_PLUS:
        case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
                gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
                auxgpio = gpio;
                break;
@@ -302,6 +304,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        case CX88_BOARD_WINFAST2000XP_EXPERT:
        case CX88_BOARD_WINFAST_DTV1000:
        case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
                ir_codes = RC_MAP_WINFAST;
                ir->gpio_addr = MO_GP0_IO;
                ir->mask_keycode = 0x8f8;
index fa8d307e1a3d2299618bdf5266aea118b68f7670..c9659def2a787d79ecfa97c5cc56ff62b4521e47 100644 (file)
@@ -244,6 +244,8 @@ extern const struct sram_channel const cx88_sram_channels[];
 #define CX88_BOARD_TEVII_S464              86
 #define CX88_BOARD_WINFAST_DTV2000H_PLUS   87
 #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
index bd443ee76fff2a342b5c7633969affdbadfa480e..f83baf3a52b0b7ae40f0e05091b2cb90147e2d4a 100644 (file)
@@ -1069,15 +1069,4 @@ static struct platform_driver dm355_ccdc_driver = {
        .probe = dm355_ccdc_probe,
 };
 
-static int __init dm355_ccdc_init(void)
-{
-       return platform_driver_register(&dm355_ccdc_driver);
-}
-
-static void __exit dm355_ccdc_exit(void)
-{
-       platform_driver_unregister(&dm355_ccdc_driver);
-}
-
-module_init(dm355_ccdc_init);
-module_exit(dm355_ccdc_exit);
+module_platform_driver(dm355_ccdc_driver);
index 8051c2956478d9ff826839874b34338ca675dcc8..9303fe553b075899e09e529173373de77af5a871 100644 (file)
@@ -1078,15 +1078,4 @@ static struct platform_driver dm644x_ccdc_driver = {
        .probe = dm644x_ccdc_probe,
 };
 
-static int __init dm644x_ccdc_init(void)
-{
-       return platform_driver_register(&dm644x_ccdc_driver);
-}
-
-static void __exit dm644x_ccdc_exit(void)
-{
-       platform_driver_unregister(&dm644x_ccdc_driver);
-}
-
-module_init(dm644x_ccdc_init);
-module_exit(dm644x_ccdc_exit);
+module_platform_driver(dm644x_ccdc_driver);
index 29c29c668596276c8c4ebeb366cd482439209d3c..1e63852374bed0641e443c9c0237dc7868c90598 100644 (file)
@@ -1156,17 +1156,6 @@ static struct platform_driver isif_driver = {
        .probe = isif_probe,
 };
 
-static int __init isif_init(void)
-{
-       return platform_driver_register(&isif_driver);
-}
-
-static void isif_exit(void)
-{
-       platform_driver_unregister(&isif_driver);
-}
-
-module_init(isif_init);
-module_exit(isif_exit);
+module_platform_driver(isif_driver);
 
 MODULE_LICENSE("GPL");
index d773d30de221f0bc7d5fd04e6ea660ff9b2f3940..c4a82a1a8a977f42431e47e5fba269173c48c272 100644 (file)
@@ -141,11 +141,12 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
        return 0;
 }
 
-static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode)
+static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode,
+                             int output_index)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        struct vpbe_enc_mode_info var;
-       int curr_output = vpbe_dev->current_out_index;
+       int curr_output = output_index;
        int i;
 
        if (NULL == mode)
@@ -245,6 +246,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
        struct encoder_config_info *curr_enc_info =
                        vpbe_current_encoder_info(vpbe_dev);
        struct vpbe_config *cfg = vpbe_dev->cfg;
+       struct venc_platform_data *venc_device = vpbe_dev->venc_device;
+       enum v4l2_mbus_pixelcode if_params;
        int enc_out_index;
        int sd_index;
        int ret = 0;
@@ -274,6 +277,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
                        goto out;
                }
 
+               if_params = cfg->outputs[index].if_params;
+               venc_device->setup_if_config(if_params);
                if (ret)
                        goto out;
        }
@@ -293,7 +298,7 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
         * encoder.
         */
        ret = vpbe_get_mode_info(vpbe_dev,
-                                cfg->outputs[index].default_mode);
+                                cfg->outputs[index].default_mode, index);
        if (!ret) {
                struct osd_state *osd_device = vpbe_dev->osd_device;
 
@@ -367,6 +372,11 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
 
        ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
                                        s_dv_preset, dv_preset);
+       if (!ret && (vpbe_dev->amp != NULL)) {
+               /* Call amplifier subdevice */
+               ret = v4l2_subdev_call(vpbe_dev->amp, video,
+                               s_dv_preset, dv_preset);
+       }
        /* set the lcd controller output for the given mode */
        if (!ret) {
                struct osd_state *osd_device = vpbe_dev->osd_device;
@@ -566,6 +576,8 @@ static int platform_device_get(struct device *dev, void *data)
 
        if (strcmp("vpbe-osd", pdev->name) == 0)
                vpbe_dev->osd_device = platform_get_drvdata(pdev);
+       if (strcmp("vpbe-venc", pdev->name) == 0)
+               vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
 
        return 0;
 }
@@ -584,6 +596,7 @@ static int platform_device_get(struct device *dev, void *data)
 static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
 {
        struct encoder_config_info *enc_info;
+       struct amp_config_info *amp_info;
        struct v4l2_subdev **enc_subdev;
        struct osd_state *osd_device;
        struct i2c_adapter *i2c_adap;
@@ -704,6 +717,32 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
                        v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
                                 " currently not supported");
        }
+       /* Add amplifier subdevice for dm365 */
+       if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
+                       vpbe_dev->cfg->amp != NULL) {
+               amp_info = vpbe_dev->cfg->amp;
+               if (amp_info->is_i2c) {
+                       vpbe_dev->amp = v4l2_i2c_new_subdev_board(
+                       &vpbe_dev->v4l2_dev, i2c_adap,
+                       &amp_info->board_info, NULL);
+                       if (!vpbe_dev->amp) {
+                               v4l2_err(&vpbe_dev->v4l2_dev,
+                                        "amplifier %s failed to register",
+                                        amp_info->module_name);
+                               ret = -ENODEV;
+                               goto vpbe_fail_amp_register;
+                       }
+                       v4l2_info(&vpbe_dev->v4l2_dev,
+                                         "v4l2 sub device %s registered\n",
+                                         amp_info->module_name);
+               } else {
+                           vpbe_dev->amp = NULL;
+                           v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
+                           " currently not supported");
+               }
+       } else {
+           vpbe_dev->amp = NULL;
+       }
 
        /* set the current encoder and output to that of venc by default */
        vpbe_dev->current_sd_index = 0;
@@ -731,6 +770,8 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
        /* TBD handling of bootargs for default output and mode */
        return 0;
 
+vpbe_fail_amp_register:
+       kfree(vpbe_dev->amp);
 vpbe_fail_sd_register:
        kfree(vpbe_dev->encoders);
 vpbe_fail_v4l2_device:
@@ -757,6 +798,7 @@ static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
        if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
                clk_put(vpbe_dev->dac_clk);
 
+       kfree(vpbe_dev->amp);
        kfree(vpbe_dev->encoders);
        vpbe_dev->initialized = 0;
        /* disable vpss clocks */
@@ -811,8 +853,10 @@ static __devinit int vpbe_probe(struct platform_device *pdev)
 
        if (cfg->outputs->num_modes > 0)
                vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
-       else
+       else {
+               kfree(vpbe_dev);
                return -ENODEV;
+       }
 
        /* set the driver data in platform device */
        platform_set_drvdata(pdev, vpbe_dev);
@@ -839,26 +883,4 @@ static struct platform_driver vpbe_driver = {
        .remove = vpbe_remove,
 };
 
-/**
- * vpbe_init: initialize the vpbe driver
- *
- * This function registers device and driver to the kernel
- */
-static __init int vpbe_init(void)
-{
-       return platform_driver_register(&vpbe_driver);
-}
-
-/**
- * vpbe_cleanup : cleanup function for vpbe driver
- *
- * This will un-registers the device and driver to the kernel
- */
-static void vpbe_cleanup(void)
-{
-       platform_driver_unregister(&vpbe_driver);
-}
-
-/* Function for module initialization and cleanup */
-module_init(vpbe_init);
-module_exit(vpbe_cleanup);
+module_platform_driver(vpbe_driver);
index 8588a86d9b45ecb31335924b5259499fd310d69c..1f3b1c72925297efd8cb549dc206b18b77eab497 100644 (file)
@@ -1746,15 +1746,16 @@ static __devinit int vpbe_display_probe(struct platform_device *pdev)
        for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
                if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
                        err = -ENODEV;
-                       goto probe_out;
+                       goto probe_out_irq;
                }
        }
 
        printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
        return 0;
 
-probe_out:
+probe_out_irq:
        free_irq(res->start, disp_dev);
+probe_out:
        for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
                /* Get the pointer to the layer object */
                vpbe_display_layer = disp_dev->dev[k];
@@ -1816,43 +1817,7 @@ static struct platform_driver vpbe_display_driver = {
        .remove = __devexit_p(vpbe_display_remove),
 };
 
-/*
- * vpbe_display_init()
- * This function registers device and driver to the kernel, requests irq
- * handler and allocates memory for layer objects
- */
-static __devinit int vpbe_display_init(void)
-{
-       int err;
-
-       printk(KERN_DEBUG "vpbe_display_init\n");
-
-       /* Register driver to the kernel */
-       err = platform_driver_register(&vpbe_display_driver);
-       if (0 != err)
-               return err;
-
-       printk(KERN_DEBUG "vpbe_display_init:"
-                       "VPBE V4L2 Display Driver V1.0 loaded\n");
-       return 0;
-}
-
-/*
- * vpbe_display_cleanup()
- * This function un-registers device and driver to the kernel, frees requested
- * irq handler and de-allocates memory allocated for layer objects.
- */
-static void vpbe_display_cleanup(void)
-{
-       printk(KERN_DEBUG "vpbe_display_cleanup\n");
-
-       /* platform driver unregister */
-       platform_driver_unregister(&vpbe_display_driver);
-}
-
-/* Function for module initialization and cleanup */
-module_init(vpbe_display_init);
-module_exit(vpbe_display_cleanup);
+module_platform_driver(vpbe_display_driver);
 
 MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller");
 MODULE_LICENSE("GPL");
index ceccf43025189743960ac711bae3cf8c01b4cda6..d6488b79ae3b54602e09170372b03bbbe8f3929a 100644 (file)
@@ -248,11 +248,29 @@ static void _osd_set_rec601_attenuation(struct osd_state *sd,
                osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
                          enable ? OSD_OSDWIN0MD_ATN0E : 0,
                          OSD_OSDWIN0MD);
+               if (sd->vpbe_type == VPBE_VERSION_1)
+                       osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
+                                 enable ? OSD_OSDWIN0MD_ATN0E : 0,
+                                 OSD_OSDWIN0MD);
+               else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+                          (sd->vpbe_type == VPBE_VERSION_2))
+                       osd_modify(sd, OSD_EXTMODE_ATNOSD0EN,
+                                 enable ? OSD_EXTMODE_ATNOSD0EN : 0,
+                                 OSD_EXTMODE);
                break;
        case OSDWIN_OSD1:
                osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
                          enable ? OSD_OSDWIN1MD_ATN1E : 0,
                          OSD_OSDWIN1MD);
+               if (sd->vpbe_type == VPBE_VERSION_1)
+                       osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
+                                 enable ? OSD_OSDWIN1MD_ATN1E : 0,
+                                 OSD_OSDWIN1MD);
+               else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+                          (sd->vpbe_type == VPBE_VERSION_2))
+                       osd_modify(sd, OSD_EXTMODE_ATNOSD1EN,
+                                 enable ? OSD_EXTMODE_ATNOSD1EN : 0,
+                                 OSD_EXTMODE);
                break;
        }
 }
@@ -273,15 +291,71 @@ static void _osd_set_blending_factor(struct osd_state *sd,
        }
 }
 
+static void _osd_enable_rgb888_pixblend(struct osd_state *sd,
+                                       enum osd_win_layer osdwin)
+{
+
+       osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL);
+       switch (osdwin) {
+       case OSDWIN_OSD0:
+               osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR,
+                         OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE);
+               break;
+       case OSDWIN_OSD1:
+               osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR,
+                         OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE);
+               break;
+       }
+}
+
 static void _osd_enable_color_key(struct osd_state *sd,
                                  enum osd_win_layer osdwin,
                                  unsigned colorkey,
                                  enum osd_pix_format pixfmt)
 {
        switch (pixfmt) {
+       case PIXFMT_1BPP:
+       case PIXFMT_2BPP:
+       case PIXFMT_4BPP:
+       case PIXFMT_8BPP:
+               if (sd->vpbe_type == VPBE_VERSION_3) {
+                       switch (osdwin) {
+                       case OSDWIN_OSD0:
+                               osd_modify(sd, OSD_TRANSPBMPIDX_BMP0,
+                                         colorkey <<
+                                         OSD_TRANSPBMPIDX_BMP0_SHIFT,
+                                         OSD_TRANSPBMPIDX);
+                               break;
+                       case OSDWIN_OSD1:
+                               osd_modify(sd, OSD_TRANSPBMPIDX_BMP1,
+                                         colorkey <<
+                                         OSD_TRANSPBMPIDX_BMP1_SHIFT,
+                                         OSD_TRANSPBMPIDX);
+                               break;
+                       }
+               }
+               break;
        case PIXFMT_RGB565:
-               osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
-                         OSD_TRANSPVAL);
+               if (sd->vpbe_type == VPBE_VERSION_1)
+                       osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
+                                 OSD_TRANSPVAL);
+               else if (sd->vpbe_type == VPBE_VERSION_3)
+                       osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
+                                 OSD_TRANSPVALL);
+               break;
+       case PIXFMT_YCbCrI:
+       case PIXFMT_YCrCbI:
+               if (sd->vpbe_type == VPBE_VERSION_3)
+                       osd_modify(sd, OSD_TRANSPVALU_Y, colorkey,
+                                  OSD_TRANSPVALU);
+               break;
+       case PIXFMT_RGB888:
+               if (sd->vpbe_type == VPBE_VERSION_3) {
+                       osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
+                                 OSD_TRANSPVALL);
+                       osd_modify(sd, OSD_TRANSPVALU_RGBU, colorkey >> 16,
+                                 OSD_TRANSPVALU);
+               }
                break;
        default:
                break;
@@ -470,23 +544,188 @@ static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
        return 0;
 }
 
+#define OSD_SRC_ADDR_HIGH4     0x7800000
+#define OSD_SRC_ADDR_HIGH7     0x7F0000
+#define OSD_SRCADD_OFSET_SFT   23
+#define OSD_SRCADD_ADD_SFT     16
+#define OSD_WINADL_MASK                0xFFFF
+#define OSD_WINOFST_MASK       0x1000
+#define VPBE_REG_BASE          0x80000000
+
 static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
                             unsigned long fb_base_phys,
                             unsigned long cbcr_ofst)
 {
-       switch (layer) {
-       case WIN_OSD0:
-               osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
-               break;
-       case WIN_VID0:
-               osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
-               break;
-       case WIN_OSD1:
-               osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
-               break;
-       case WIN_VID1:
-               osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
-               break;
+
+       if (sd->vpbe_type == VPBE_VERSION_1) {
+               switch (layer) {
+               case WIN_OSD0:
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
+                       break;
+               case WIN_VID0:
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
+                       break;
+               case WIN_OSD1:
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
+                       break;
+               case WIN_VID1:
+                       osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
+                       break;
+             }
+       } else if (sd->vpbe_type == VPBE_VERSION_3) {
+               unsigned long fb_offset_32 =
+                   (fb_base_phys - VPBE_REG_BASE) >> 5;
+
+               switch (layer) {
+               case WIN_OSD0:
+                       osd_modify(sd, OSD_OSDWINADH_O0AH,
+                                 fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+                                                  OSD_OSDWINADH_O0AH_SHIFT),
+                                 OSD_OSDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_OSDWIN0ADL_O0AL,
+                                 OSD_OSDWIN0ADL);
+                       break;
+               case WIN_VID0:
+                       osd_modify(sd, OSD_VIDWINADH_V0AH,
+                                 fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+                                                  OSD_VIDWINADH_V0AH_SHIFT),
+                                 OSD_VIDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_VIDWIN0ADL_V0AL,
+                                 OSD_VIDWIN0ADL);
+                       break;
+               case WIN_OSD1:
+                       osd_modify(sd, OSD_OSDWINADH_O1AH,
+                                 fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+                                                  OSD_OSDWINADH_O1AH_SHIFT),
+                                 OSD_OSDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_OSDWIN1ADL_O1AL,
+                                 OSD_OSDWIN1ADL);
+                       break;
+               case WIN_VID1:
+                       osd_modify(sd, OSD_VIDWINADH_V1AH,
+                                 fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+                                                  OSD_VIDWINADH_V1AH_SHIFT),
+                                 OSD_VIDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_VIDWIN1ADL_V1AL,
+                                 OSD_VIDWIN1ADL);
+                       break;
+               }
+       } else if (sd->vpbe_type == VPBE_VERSION_2) {
+               struct osd_window_state *win = &sd->win[layer];
+               unsigned long fb_offset_32, cbcr_offset_32;
+
+               fb_offset_32 = fb_base_phys - VPBE_REG_BASE;
+               if (cbcr_ofst)
+                       cbcr_offset_32 = cbcr_ofst;
+               else
+                       cbcr_offset_32 = win->lconfig.line_length *
+                                        win->lconfig.ysize;
+               cbcr_offset_32 += fb_offset_32;
+               fb_offset_32 = fb_offset_32 >> 5;
+               cbcr_offset_32 = cbcr_offset_32 >> 5;
+               /*
+                * DM365: start address is 27-bit long address b26 - b23 are
+                * in offset register b12 - b9, and * bit 26 has to be '1'
+                */
+               if (win->lconfig.pixfmt == PIXFMT_NV12) {
+                       switch (layer) {
+                       case WIN_VID0:
+                       case WIN_VID1:
+                               /* Y is in VID0 */
+                               osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
+                                        ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+                                        (OSD_SRCADD_OFSET_SFT -
+                                        OSD_WINOFST_AH_SHIFT)) |
+                                        OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
+                               osd_modify(sd, OSD_VIDWINADH_V0AH,
+                                         (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+                                         (OSD_SRCADD_ADD_SFT -
+                                         OSD_VIDWINADH_V0AH_SHIFT),
+                                          OSD_VIDWINADH);
+                               osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+                                         OSD_VIDWIN0ADL);
+                               /* CbCr is in VID1 */
+                               osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
+                                        ((cbcr_offset_32 &
+                                        OSD_SRC_ADDR_HIGH4) >>
+                                        (OSD_SRCADD_OFSET_SFT -
+                                        OSD_WINOFST_AH_SHIFT)) |
+                                        OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
+                               osd_modify(sd, OSD_VIDWINADH_V1AH,
+                                         (cbcr_offset_32 &
+                                         OSD_SRC_ADDR_HIGH7) >>
+                                         (OSD_SRCADD_ADD_SFT -
+                                         OSD_VIDWINADH_V1AH_SHIFT),
+                                         OSD_VIDWINADH);
+                               osd_write(sd, cbcr_offset_32 & OSD_WINADL_MASK,
+                                         OSD_VIDWIN1ADL);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               switch (layer) {
+               case WIN_OSD0:
+                       osd_modify(sd, OSD_OSDWIN0OFST_O0AH,
+                                ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+                                (OSD_SRCADD_OFSET_SFT -
+                                OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
+                                 OSD_OSDWIN0OFST);
+                       osd_modify(sd, OSD_OSDWINADH_O0AH,
+                                (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+                                (OSD_SRCADD_ADD_SFT -
+                                OSD_OSDWINADH_O0AH_SHIFT), OSD_OSDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+                                       OSD_OSDWIN0ADL);
+                       break;
+               case WIN_VID0:
+                       if (win->lconfig.pixfmt != PIXFMT_NV12) {
+                               osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
+                                        ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+                                        (OSD_SRCADD_OFSET_SFT -
+                                        OSD_WINOFST_AH_SHIFT)) |
+                                        OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
+                               osd_modify(sd, OSD_VIDWINADH_V0AH,
+                                         (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+                                         (OSD_SRCADD_ADD_SFT -
+                                         OSD_VIDWINADH_V0AH_SHIFT),
+                                         OSD_VIDWINADH);
+                               osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+                                         OSD_VIDWIN0ADL);
+                       }
+                       break;
+               case WIN_OSD1:
+                       osd_modify(sd, OSD_OSDWIN1OFST_O1AH,
+                                ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+                                (OSD_SRCADD_OFSET_SFT -
+                                OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
+                                 OSD_OSDWIN1OFST);
+                       osd_modify(sd, OSD_OSDWINADH_O1AH,
+                                 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+                                 (OSD_SRCADD_ADD_SFT -
+                                 OSD_OSDWINADH_O1AH_SHIFT),
+                                 OSD_OSDWINADH);
+                       osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+                                       OSD_OSDWIN1ADL);
+                       break;
+               case WIN_VID1:
+                       if (win->lconfig.pixfmt != PIXFMT_NV12) {
+                               osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
+                                        ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+                                        (OSD_SRCADD_OFSET_SFT -
+                                        OSD_WINOFST_AH_SHIFT)) |
+                                        OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
+                               osd_modify(sd, OSD_VIDWINADH_V1AH,
+                                         (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+                                         (OSD_SRCADD_ADD_SFT -
+                                         OSD_VIDWINADH_V1AH_SHIFT),
+                                         OSD_VIDWINADH);
+                               osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+                                         OSD_VIDWIN1ADL);
+                       }
+                       break;
+               }
        }
 }
 
@@ -545,7 +784,7 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
 {
        struct osd_state *osd = sd;
        struct osd_window_state *win = &osd->win[layer];
-       int bad_config;
+       int bad_config = 0;
 
        /* verify that the pixel format is compatible with the layer */
        switch (lconfig->pixfmt) {
@@ -554,17 +793,25 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
        case PIXFMT_4BPP:
        case PIXFMT_8BPP:
        case PIXFMT_RGB565:
-               bad_config = !is_osd_win(layer);
+               if (osd->vpbe_type == VPBE_VERSION_1)
+                       bad_config = !is_vid_win(layer);
                break;
        case PIXFMT_YCbCrI:
        case PIXFMT_YCrCbI:
                bad_config = !is_vid_win(layer);
                break;
        case PIXFMT_RGB888:
-               bad_config = !is_vid_win(layer);
+               if (osd->vpbe_type == VPBE_VERSION_1)
+                       bad_config = !is_vid_win(layer);
+               else if ((osd->vpbe_type == VPBE_VERSION_3) ||
+                        (osd->vpbe_type == VPBE_VERSION_2))
+                       bad_config = !is_osd_win(layer);
                break;
        case PIXFMT_NV12:
-               bad_config = 1;
+               if (osd->vpbe_type != VPBE_VERSION_2)
+                       bad_config = 1;
+               else
+                       bad_config = is_osd_win(layer);
                break;
        case PIXFMT_OSD_ATTR:
                bad_config = (layer != WIN_OSD1);
@@ -584,7 +831,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
 
        /* DM6446: */
        /* only one OSD window at a time can use RGB pixel formats */
-       if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
+         if ((osd->vpbe_type == VPBE_VERSION_1) &&
+                 is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
                enum osd_pix_format pixfmt;
                if (layer == WIN_OSD0)
                        pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
@@ -602,7 +850,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
        }
 
        /* DM6446: only one video window at a time can use RGB888 */
-       if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) {
+       if ((osd->vpbe_type == VPBE_VERSION_1) && is_vid_win(layer) &&
+               lconfig->pixfmt == PIXFMT_RGB888) {
                enum osd_pix_format pixfmt;
 
                if (layer == WIN_VID0)
@@ -652,7 +901,8 @@ static void _osd_disable_vid_rgb888(struct osd_state *sd)
         * The caller must ensure that neither video window is currently
         * configured for RGB888 pixel format.
         */
-       osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+       if (sd->vpbe_type == VPBE_VERSION_1)
+               osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
 }
 
 static void _osd_enable_vid_rgb888(struct osd_state *sd,
@@ -665,13 +915,14 @@ static void _osd_enable_vid_rgb888(struct osd_state *sd,
         * currently configured for RGB888 pixel format, as this routine will
         * disable RGB888 pixel format for the other window.
         */
-       if (layer == WIN_VID0) {
-               osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
-                         OSD_MISCCTL_RGBEN, OSD_MISCCTL);
-       } else if (layer == WIN_VID1) {
-               osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
-                         OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
-                         OSD_MISCCTL);
+       if (sd->vpbe_type == VPBE_VERSION_1) {
+               if (layer == WIN_VID0)
+                       osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                                 OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+               else if (layer == WIN_VID1)
+                       osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                                 OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+                                 OSD_MISCCTL);
        }
 }
 
@@ -697,9 +948,30 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
 
        switch (layer) {
        case WIN_OSD0:
-               winmd_mask |= OSD_OSDWIN0MD_RGB0E;
-               if (lconfig->pixfmt == PIXFMT_RGB565)
-                       winmd |= OSD_OSDWIN0MD_RGB0E;
+               if (sd->vpbe_type == VPBE_VERSION_1) {
+                       winmd_mask |= OSD_OSDWIN0MD_RGB0E;
+                       if (lconfig->pixfmt == PIXFMT_RGB565)
+                               winmd |= OSD_OSDWIN0MD_RGB0E;
+               } else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+                 (sd->vpbe_type == VPBE_VERSION_2)) {
+                       winmd_mask |= OSD_OSDWIN0MD_BMP0MD;
+                       switch (lconfig->pixfmt) {
+                       case PIXFMT_RGB565:
+                                       winmd |= (1 <<
+                                       OSD_OSDWIN0MD_BMP0MD_SHIFT);
+                                       break;
+                       case PIXFMT_RGB888:
+                               winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
+                               _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0);
+                               break;
+                       case PIXFMT_YCbCrI:
+                       case PIXFMT_YCrCbI:
+                               winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
+                               break;
+                       default:
+                               break;
+                       }
+               }
 
                winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
 
@@ -749,12 +1021,59 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
                 * For YUV420P format the register contents are
                 * duplicated in both VID registers
                 */
+               if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               (lconfig->pixfmt == PIXFMT_NV12)) {
+                       /* other window also */
+                       if (lconfig->interlaced) {
+                               winmd_mask |= OSD_VIDWINMD_VFF1;
+                               winmd |= OSD_VIDWINMD_VFF1;
+                               osd_modify(sd, winmd_mask, winmd,
+                                         OSD_VIDWINMD);
+                       }
+
+                       osd_modify(sd, OSD_MISCCTL_S420D,
+                                   OSD_MISCCTL_S420D, OSD_MISCCTL);
+                       osd_write(sd, lconfig->line_length >> 5,
+                                 OSD_VIDWIN1OFST);
+                       osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
+                       osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
+                       /*
+                         * if NV21 pixfmt and line length not 32B
+                         * aligned (e.g. NTSC), Need to set window
+                         * X pixel size to be 32B aligned as well
+                         */
+                       if (lconfig->xsize % 32) {
+                               osd_write(sd,
+                                         ((lconfig->xsize + 31) & ~31),
+                                         OSD_VIDWIN1XL);
+                               osd_write(sd,
+                                         ((lconfig->xsize + 31) & ~31),
+                                         OSD_VIDWIN0XL);
+                       }
+               } else if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               (lconfig->pixfmt != PIXFMT_NV12)) {
+                       osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
+                                               OSD_MISCCTL);
+               }
+
                if (lconfig->interlaced) {
                        osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
                        osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
+                       if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               lconfig->pixfmt == PIXFMT_NV12) {
+                               osd_write(sd, lconfig->ypos >> 1,
+                                         OSD_VIDWIN1YP);
+                               osd_write(sd, lconfig->ysize >> 1,
+                                         OSD_VIDWIN1YL);
+                       }
                } else {
                        osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
                        osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
+                       if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               lconfig->pixfmt == PIXFMT_NV12) {
+                               osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
+                               osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
+                       }
                }
                break;
        case WIN_OSD1:
@@ -764,14 +1083,43 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
                 * attribute mode to a normal mode.
                 */
                if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
-                       winmd_mask |=
-                           OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E |
-                           OSD_OSDWIN1MD_CLUTS1 |
-                           OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
+                       if (sd->vpbe_type == VPBE_VERSION_1) {
+                               winmd_mask |= OSD_OSDWIN1MD_ATN1E |
+                               OSD_OSDWIN1MD_RGB1E | OSD_OSDWIN1MD_CLUTS1 |
+                               OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
+                       } else {
+                               winmd_mask |= OSD_OSDWIN1MD_BMP1MD |
+                               OSD_OSDWIN1MD_CLUTS1 | OSD_OSDWIN1MD_BLND1 |
+                               OSD_OSDWIN1MD_TE1;
+                       }
                } else {
-                       winmd_mask |= OSD_OSDWIN1MD_RGB1E;
-                       if (lconfig->pixfmt == PIXFMT_RGB565)
-                               winmd |= OSD_OSDWIN1MD_RGB1E;
+                       if (sd->vpbe_type == VPBE_VERSION_1) {
+                               winmd_mask |= OSD_OSDWIN1MD_RGB1E;
+                               if (lconfig->pixfmt == PIXFMT_RGB565)
+                                       winmd |= OSD_OSDWIN1MD_RGB1E;
+                       } else if ((sd->vpbe_type == VPBE_VERSION_3)
+                                  || (sd->vpbe_type == VPBE_VERSION_2)) {
+                               winmd_mask |= OSD_OSDWIN1MD_BMP1MD;
+                               switch (lconfig->pixfmt) {
+                               case PIXFMT_RGB565:
+                                       winmd |=
+                                           (1 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+                                       break;
+                               case PIXFMT_RGB888:
+                                       winmd |=
+                                           (2 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+                                       _osd_enable_rgb888_pixblend(sd,
+                                                       OSDWIN_OSD1);
+                                       break;
+                               case PIXFMT_YCbCrI:
+                               case PIXFMT_YCrCbI:
+                                       winmd |=
+                                           (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
 
                        winmd_mask |= OSD_OSDWIN1MD_BMW1;
                        switch (lconfig->pixfmt) {
@@ -822,15 +1170,45 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
                 * For YUV420P format the register contents are
                 * duplicated in both VID registers
                 */
-               osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
-                          OSD_MISCCTL);
+               if (sd->vpbe_type == VPBE_VERSION_2) {
+                       if (lconfig->pixfmt == PIXFMT_NV12) {
+                               /* other window also */
+                               if (lconfig->interlaced) {
+                                       winmd_mask |= OSD_VIDWINMD_VFF0;
+                                       winmd |= OSD_VIDWINMD_VFF0;
+                                       osd_modify(sd, winmd_mask, winmd,
+                                                 OSD_VIDWINMD);
+                               }
+                               osd_modify(sd, OSD_MISCCTL_S420D,
+                                          OSD_MISCCTL_S420D, OSD_MISCCTL);
+                               osd_write(sd, lconfig->line_length >> 5,
+                                         OSD_VIDWIN0OFST);
+                               osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
+                               osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
+                       } else {
+                               osd_modify(sd, OSD_MISCCTL_S420D,
+                                          ~OSD_MISCCTL_S420D, OSD_MISCCTL);
+                       }
+               }
 
                if (lconfig->interlaced) {
                        osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
                        osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
+                       if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               lconfig->pixfmt == PIXFMT_NV12) {
+                               osd_write(sd, lconfig->ypos >> 1,
+                                         OSD_VIDWIN0YP);
+                               osd_write(sd, lconfig->ysize >> 1,
+                                         OSD_VIDWIN0YL);
+                       }
                } else {
                        osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
                        osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
+                       if ((sd->vpbe_type == VPBE_VERSION_2) &&
+                               lconfig->pixfmt == PIXFMT_NV12) {
+                               osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
+                               osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
+                       }
                }
                break;
        }
@@ -1089,6 +1467,11 @@ static void _osd_init(struct osd_state *sd)
        osd_write(sd, 0, OSD_OSDWIN1MD);
        osd_write(sd, 0, OSD_RECTCUR);
        osd_write(sd, 0, OSD_MISCCTL);
+       if (sd->vpbe_type == VPBE_VERSION_3) {
+               osd_write(sd, 0, OSD_VBNDRY);
+               osd_write(sd, 0, OSD_EXTMODE);
+               osd_write(sd, OSD_MISCCTL_DMANG, OSD_MISCCTL);
+       }
 }
 
 static void osd_set_left_margin(struct osd_state *sd, u32 val)
@@ -1110,6 +1493,14 @@ static int osd_initialize(struct osd_state *osd)
        /* set default Cb/Cr order */
        osd->yc_pixfmt = PIXFMT_YCbCrI;
 
+       if (osd->vpbe_type == VPBE_VERSION_3) {
+               /*
+                * ROM CLUT1 on the DM355 is similar (identical?) to ROM CLUT0
+                * on the DM6446, so make ROM_CLUT1 the default on the DM355.
+                */
+               osd->rom_clut = ROM_CLUT1;
+       }
+
        _osd_set_field_inversion(osd, osd->field_inversion);
        _osd_set_rom_clut(osd, osd->rom_clut);
 
@@ -1208,23 +1599,7 @@ static struct platform_driver osd_driver = {
        },
 };
 
-static int osd_init(void)
-{
-       if (platform_driver_register(&osd_driver)) {
-               printk(KERN_ERR "Unable to register davinci osd driver\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static void osd_exit(void)
-{
-       platform_driver_unregister(&osd_driver);
-}
-
-module_init(osd_init);
-module_exit(osd_exit);
+module_platform_driver(osd_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
index 03a3e5c65ee78c53c017096ca55cf35d81ec0402..00e80f59d5d5339c6f0e835e9f82103d328be7f5 100644 (file)
@@ -99,6 +99,8 @@ static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
        return val;
 }
 
+#define VDAC_COMPONENT 0x543
+#define VDAC_S_VIDEO   0x210
 /* This function sets the dac of the VPBE for various outputs
  */
 static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
@@ -109,11 +111,12 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
                venc_write(sd, VENC_DACSEL, 0);
                break;
        case 1:
-               v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n");
-               venc_write(sd, VENC_DACSEL, 0x210);
+               v4l2_dbg(debug, 1, sd, "Setting output to Component\n");
+               venc_write(sd, VENC_DACSEL, VDAC_COMPONENT);
                break;
-       case  2:
-               venc_write(sd, VENC_DACSEL, 0x543);
+       case 2:
+               v4l2_dbg(debug, 1, sd, "Setting output to S-video\n");
+               venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO);
                break;
        default:
                return -EINVAL;
@@ -124,6 +127,8 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
 
 static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
 {
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
        v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
 
        if (benable) {
@@ -155,7 +160,8 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
 
                /* Disable LCD output control (accepting default polarity) */
                venc_write(sd, VENC_LCDOUT, 0);
-               venc_write(sd, VENC_CMPNT, 0x100);
+               if (pdata->venc_type != VPBE_VERSION_3)
+                       venc_write(sd, VENC_CMPNT, 0x100);
                venc_write(sd, VENC_HSPLS, 0);
                venc_write(sd, VENC_HINT, 0);
                venc_write(sd, VENC_HSTART, 0);
@@ -178,11 +184,14 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
        }
 }
 
+#define VDAC_CONFIG_SD_V3      0x0E21A6B6
+#define VDAC_CONFIG_SD_V2      0x081141CF
 /*
  * setting NTSC mode
  */
 static int venc_set_ntsc(struct v4l2_subdev *sd)
 {
+       u32 val;
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
@@ -195,12 +204,22 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
-       venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
-       /* Set REC656 Mode */
-       venc_write(sd, VENC_YCCCTL, 0x1);
-       venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
-       venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
+       if (pdata->venc_type == VPBE_VERSION_3) {
+               venc_write(sd, VENC_CLKCTL, 0x01);
+               venc_write(sd, VENC_VIDCTL, 0);
+               val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
+       } else if (pdata->venc_type == VPBE_VERSION_2) {
+               venc_write(sd, VENC_CLKCTL, 0x01);
+               venc_write(sd, VENC_VIDCTL, 0);
+               vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
+       } else {
+               /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+               venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+               /* Set REC656 Mode */
+               venc_write(sd, VENC_YCCCTL, 0x1);
+               venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
+               venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
+       }
 
        venc_write(sd, VENC_VMOD, 0);
        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
@@ -220,6 +239,7 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
 static int venc_set_pal(struct v4l2_subdev *sd)
 {
        struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
 
        v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
 
@@ -230,10 +250,20 @@ static int venc_set_pal(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
-       /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
-       venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
-       /* Set REC656 Mode */
-       venc_write(sd, VENC_YCCCTL, 0x1);
+       if (pdata->venc_type == VPBE_VERSION_3) {
+               venc_write(sd, VENC_CLKCTL, 0x1);
+               venc_write(sd, VENC_VIDCTL, 0);
+               vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
+       } else if (pdata->venc_type == VPBE_VERSION_2) {
+               venc_write(sd, VENC_CLKCTL, 0x1);
+               venc_write(sd, VENC_VIDCTL, 0);
+               vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
+       } else {
+               /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+               venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+               /* Set REC656 Mode */
+               venc_write(sd, VENC_YCCCTL, 0x1);
+       }
 
        venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
                        VENC_SYNCCTL_OVD);
@@ -252,6 +282,7 @@ static int venc_set_pal(struct v4l2_subdev *sd)
        return 0;
 }
 
+#define VDAC_CONFIG_HD_V2      0x081141EF
 /*
  * venc_set_480p59_94
  *
@@ -263,6 +294,9 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
        struct venc_platform_data *pdata = venc->pdata;
 
        v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
+       if ((pdata->venc_type != VPBE_VERSION_1) &&
+           (pdata->venc_type != VPBE_VERSION_2))
+               return -EINVAL;
 
        /* Setup clock at VPSS & VENC for SD */
        if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
@@ -270,12 +304,18 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
 
        venc_enabledigitaloutput(sd, 0);
 
+       if (pdata->venc_type == VPBE_VERSION_2)
+               vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
        venc_write(sd, VENC_OSDCLK0, 0);
        venc_write(sd, VENC_OSDCLK1, 1);
-       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
-                   VENC_VDPRO_DAFRQ);
-       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
-                   VENC_VDPRO_DAUPS);
+
+       if (pdata->venc_type == VPBE_VERSION_1) {
+               venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+                           VENC_VDPRO_DAFRQ);
+               venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+                           VENC_VDPRO_DAUPS);
+       }
+
        venc_write(sd, VENC_VMOD, 0);
        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
                    VENC_VMOD_VIE);
@@ -302,19 +342,27 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
 
        v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
 
+       if ((pdata->venc_type != VPBE_VERSION_1) &&
+         (pdata->venc_type != VPBE_VERSION_2))
+               return -EINVAL;
        /* Setup clock at VPSS & VENC for SD */
        if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
 
+       if (pdata->venc_type == VPBE_VERSION_2)
+               vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+
        venc_write(sd, VENC_OSDCLK0, 0);
        venc_write(sd, VENC_OSDCLK1, 1);
 
-       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
-                   VENC_VDPRO_DAFRQ);
-       venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
-                   VENC_VDPRO_DAUPS);
+       if (pdata->venc_type == VPBE_VERSION_1) {
+               venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+                           VENC_VDPRO_DAFRQ);
+               venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+                           VENC_VDPRO_DAUPS);
+       }
 
        venc_write(sd, VENC_VMOD, 0);
        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
@@ -330,6 +378,63 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
        return 0;
 }
 
+/*
+ * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
+ */
+static int venc_set_720p60_internal(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
+
+       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       venc_write(sd, VENC_OSDCLK0, 0);
+       venc_write(sd, VENC_OSDCLK1, 1);
+
+       venc_write(sd, VENC_VMOD, 0);
+       /* DM365 component HD mode */
+       venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+           VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+       venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
+                   VENC_VMOD_TVTYP);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+       venc_write(sd, VENC_XHINTVL, 0);
+       return 0;
+}
+
+/*
+ * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
+ */
+static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
+{
+       struct venc_state *venc = to_state(sd);
+       struct venc_platform_data *pdata = venc->pdata;
+
+       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
+               return -EINVAL;
+
+       venc_enabledigitaloutput(sd, 0);
+
+       venc_write(sd, VENC_OSDCLK0, 0);
+       venc_write(sd, VENC_OSDCLK1, 1);
+
+
+       venc_write(sd, VENC_VMOD, 0);
+       /* DM365 component HD mode */
+       venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+                   VENC_VMOD_VIE);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+       venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
+                   VENC_VMOD_TVTYP);
+       venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+       venc_write(sd, VENC_XHINTVL, 0);
+       return 0;
+}
+
 static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
        v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
@@ -345,13 +450,30 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 static int venc_s_dv_preset(struct v4l2_subdev *sd,
                            struct v4l2_dv_preset *dv_preset)
 {
+       struct venc_state *venc = to_state(sd);
+       int ret;
+
        v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
 
        if (dv_preset->preset == V4L2_DV_576P50)
                return venc_set_576p50(sd);
        else if (dv_preset->preset == V4L2_DV_480P59_94)
                return venc_set_480p59_94(sd);
-
+       else if ((dv_preset->preset == V4L2_DV_720P60) &&
+                       (venc->pdata->venc_type == VPBE_VERSION_2)) {
+               /* TBD setup internal 720p mode here */
+               ret = venc_set_720p60_internal(sd);
+               /* for DM365 VPBE, there is DAC inside */
+               vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+               return ret;
+       } else if ((dv_preset->preset == V4L2_DV_1080I30) &&
+               (venc->pdata->venc_type == VPBE_VERSION_2)) {
+               /* TBD setup internal 1080i mode here */
+               ret = venc_set_1080i30_internal(sd);
+               /* for DM365 VPBE, there is DAC inside */
+               vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+               return ret;
+       }
        return -EINVAL;
 }
 
@@ -508,11 +630,41 @@ static int venc_probe(struct platform_device *pdev)
                goto release_venc_mem_region;
        }
 
+       if (venc->pdata->venc_type != VPBE_VERSION_1) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (!res) {
+                       dev_err(venc->pdev,
+                               "Unable to get VDAC_CONFIG address map\n");
+                       ret = -ENODEV;
+                       goto unmap_venc_io;
+               }
+
+               if (!request_mem_region(res->start,
+                                       resource_size(res), "venc")) {
+                       dev_err(venc->pdev,
+                               "Unable to reserve VDAC_CONFIG  MMIO region\n");
+                       ret = -ENODEV;
+                       goto unmap_venc_io;
+               }
+
+               venc->vdaccfg_reg = ioremap_nocache(res->start,
+                                                   resource_size(res));
+               if (!venc->vdaccfg_reg) {
+                       dev_err(venc->pdev,
+                               "Unable to map VDAC_CONFIG IO space\n");
+                       ret = -ENODEV;
+                       goto release_vdaccfg_mem_region;
+               }
+       }
        spin_lock_init(&venc->lock);
        platform_set_drvdata(pdev, venc);
        dev_notice(venc->pdev, "VENC sub device probe success\n");
        return 0;
 
+release_vdaccfg_mem_region:
+       release_mem_region(res->start, resource_size(res));
+unmap_venc_io:
+       iounmap(venc->venc_base);
 release_venc_mem_region:
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
@@ -529,6 +681,11 @@ static int venc_remove(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        iounmap((void *)venc->venc_base);
        release_mem_region(res->start, resource_size(res));
+       if (venc->pdata->venc_type != VPBE_VERSION_1) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               iounmap((void *)venc->vdaccfg_reg);
+               release_mem_region(res->start, resource_size(res));
+       }
        kfree(venc);
 
        return 0;
@@ -543,23 +700,7 @@ static struct platform_driver venc_driver = {
        },
 };
 
-static int venc_init(void)
-{
-       if (platform_driver_register(&venc_driver)) {
-               printk(KERN_ERR "Unable to register venc driver\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void venc_exit(void)
-{
-       platform_driver_unregister(&venc_driver);
-       return;
-}
-
-module_init(venc_init);
-module_exit(venc_exit);
+module_platform_driver(venc_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VPBE VENC Driver");
index 5b38fc93ff280c7fe8fa3e22f386ccaa31c9d824..20cf271a774b81b6c3d9b32b963287f30130f3f7 100644 (file)
@@ -2076,20 +2076,4 @@ static struct platform_driver vpfe_driver = {
        .remove = __devexit_p(vpfe_remove),
 };
 
-static __init int vpfe_init(void)
-{
-       printk(KERN_NOTICE "vpfe_init\n");
-       /* Register driver to the kernel */
-       return platform_driver_register(&vpfe_driver);
-}
-
-/*
- * vpfe_cleanup : This function un-registers device driver
- */
-static void vpfe_cleanup(void)
-{
-       platform_driver_unregister(&vpfe_driver);
-}
-
-module_init(vpfe_init);
-module_exit(vpfe_cleanup);
+module_platform_driver(vpfe_driver);
index 49e4deb500430faf3be60475b5062cf7e5141921..6504e40a31dd2fb27277253ae7166ff3da64decb 100644 (file)
@@ -2177,6 +2177,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
+       err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
+       if (err) {
+               v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
+               return err;
+       }
+
        k = 0;
        while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
@@ -2246,12 +2252,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                goto probe_out;
        }
 
-       err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
-       if (err) {
-               v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
-               goto probe_subdev_out;
-       }
-
        for (i = 0; i < subdev_count; i++) {
                subdevdata = &config->subdev_info[i];
                vpif_obj.sd[i] =
@@ -2281,7 +2281,6 @@ probe_subdev_out:
 
        j = VPIF_CAPTURE_MAX_DEVICES;
 probe_out:
-       v4l2_device_unregister(&vpif_obj.v4l2_dev);
        for (k = 0; k < j; k++) {
                /* Get the pointer to the channel object */
                ch = vpif_obj.dev[k];
@@ -2303,6 +2302,7 @@ vpif_int_err:
                if (res)
                        i = res->end;
        }
+       v4l2_device_unregister(&vpif_obj.v4l2_dev);
        return err;
 }
 
index cff0768afbf514183b50ba0e35e3bfdcbde43a6f..e2a7b77c39c79a21fbef86892cd66f2a322a95c6 100644 (file)
@@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
 
                urb->dev = dev->udev;
                urb->context = dev;
-               urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
+               urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
                urb->transfer_flags = URB_ISO_ASAP;
                urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->interval = 1;
index 93807dcf944e4be4d9a4ed4604d358fa0c2e0b90..4561cd89938de422ff268b64d5a2734d27873daa 100644 (file)
@@ -336,6 +336,23 @@ static struct em28xx_reg_seq pctv_460e[] = {
        {             -1,   -1,   -1,  -1},
 };
 
+#if 0
+static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
+       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
+       {EM2874_R80_GPIO,       0x4f,   0xff,   10}, /* xc5000 reset */
+       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
+       {EM2874_R80_GPIO,       0x4f,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+
+static struct em28xx_reg_seq hauppauge_930c_digital[] = {
+       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
+       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+#endif
+
 /*
  *  Board definitions
  */
@@ -839,6 +856,10 @@ struct em28xx_board em28xx_boards[] = {
        [EM2870_BOARD_KWORLD_355U] = {
                .name         = "Kworld 355 U DVB-T",
                .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT,
+               .tuner_gpio   = default_tuner_gpio,
+               .has_dvb      = 1,
+               .dvb_gpio     = default_digital,
        },
        [EM2870_BOARD_PINNACLE_PCTV_DVB] = {
                .name         = "Pinnacle PCTV DVB-T",
@@ -887,6 +908,37 @@ struct em28xx_board em28xx_boards[] = {
                .tuner_addr   = 0x41,
                .dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
                .tuner_gpio   = terratec_h5_gpio,
+#else
+               .tuner_type   = TUNER_ABSENT,
+#endif
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = {
+               .name         = "Hauppauge WinTV HVR 930C",
+               .has_dvb      = 1,
+#if 0 /* FIXME: Add analog support */
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0x41,
+               .dvb_gpio     = hauppauge_930c_digital,
+               .tuner_gpio   = hauppauge_930c_gpio,
+#else
+               .tuner_type   = TUNER_ABSENT,
+#endif
+               .ir_codes     = RC_MAP_HAUPPAUGE,
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       [EM2884_BOARD_CINERGY_HTC_STICK] = {
+               .name         = "Terratec Cinergy HTC Stick",
+               .has_dvb      = 1,
+#if 0
+               .tuner_type   = TUNER_PHILIPS_TDA8290,
+               .tuner_addr   = 0x41,
+               .dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
+               .tuner_gpio   = terratec_h5_gpio,
 #endif
                .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
                                EM28XX_I2C_CLK_WAIT_ENABLE |
@@ -1127,7 +1179,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Terratec Cinergy 200 USB",
                .is_em2800    = 1,
                .has_ir_i2c   = 1,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tuner_type   = TUNER_LG_TALN,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA711X,
                .input        = { {
@@ -1218,7 +1270,7 @@ struct em28xx_board em28xx_boards[] = {
        },
        [EM2820_BOARD_PINNACLE_DVC_90] = {
                .name         = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker "
-                               "/ Kworld DVD Maker 2",
+                              "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
                .tuner_type   = TUNER_ABSENT, /* capture only board */
                .decoder      = EM28XX_SAA711X,
                .input        = { {
@@ -1840,6 +1892,22 @@ struct em28xx_board em28xx_boards[] = {
                .has_dvb       = 1,
                .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
        },
+       /* eb1a:5006 Honestech VIDBOX NW03
+        * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */
+       [EM2860_BOARD_HT_VIDBOX_NW03] = {
+               .name                = "Honestech Vidbox NW03",
+               .tuner_type          = TUNER_ABSENT,
+               .decoder             = EM28XX_SAA711X,
+               .input               = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,  /* S-VIDEO needs confirming */
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -1899,6 +1967,8 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
        { USB_DEVICE(0xeb1a, 0xe357),
                        .driver_info = EM2870_BOARD_KWORLD_355U },
+       { USB_DEVICE(0xeb1a, 0xe359),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
        { USB_DEVICE(0x1b80, 0xe302),
                        .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
        { USB_DEVICE(0x1b80, 0xe304),
@@ -1914,17 +1984,23 @@ struct usb_device_id em28xx_id_table[] = {
        { USB_DEVICE(0x0ccd, 0x0042),
                        .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
        { USB_DEVICE(0x0ccd, 0x0043),
+                       .driver_info = EM2870_BOARD_TERRATEC_XS },
+       { USB_DEVICE(0x0ccd, 0x008e),   /* Cinergy HTC USB XS Rev. 1 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x00ac),   /* Cinergy HTC USB XS Rev. 2 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x10a2),   /* H5 Rev. 1 */
                        .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x10a2),   /* Rev. 1 */
+       { USB_DEVICE(0x0ccd, 0x10ad),   /* H5 Rev. 2 */
                        .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x10ad),   /* Rev. 2 */
-                       .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
        { USB_DEVICE(0x0ccd, 0x0084),
                        .driver_info = EM2860_BOARD_TERRATEC_AV350 },
        { USB_DEVICE(0x0ccd, 0x0096),
                        .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
        { USB_DEVICE(0x0ccd, 0x10AF),
                        .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+       { USB_DEVICE(0x0ccd, 0x00b2),
+                       .driver_info = EM2884_BOARD_CINERGY_HTC_STICK },
        { USB_DEVICE(0x0fd9, 0x0033),
                        .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
        { USB_DEVICE(0x185b, 0x2870),
@@ -1963,6 +2039,8 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
        { USB_DEVICE(0x0413, 0x6023),
                        .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
+       { USB_DEVICE(0x093b, 0xa003),
+                      .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
        { USB_DEVICE(0x093b, 0xa005),
                        .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
        { USB_DEVICE(0x04bb, 0x0515),
@@ -1975,6 +2053,12 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM28174_BOARD_PCTV_290E },
        { USB_DEVICE(0x2013, 0x024c),
                        .driver_info = EM28174_BOARD_PCTV_460E },
+       { USB_DEVICE(0x2040, 0x1605),
+                       .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C },
+       { USB_DEVICE(0xeb1a, 0x5006),
+                       .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 },
+       { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */
+                       .driver_info = EM2860_BOARD_EASYCAP },
        { },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2028,10 +2112,10 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
        int rc = 0;
        struct em28xx *dev = ptr;
 
-       if (dev->tuner_type != TUNER_XC2028)
+       if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000)
                return 0;
 
-       if (command != XC2028_TUNER_RESET)
+       if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET)
                return 0;
 
        rc = em28xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2203,7 +2287,8 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        /* Set the initial XCLK and I2C clock values based on the board
           definition */
        em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+       if (!dev->board.is_em2800)
+               em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
        msleep(50);
 
        /* request some modules */
@@ -2832,11 +2917,10 @@ void em28xx_release_resources(struct em28xx *dev)
  * em28xx_init_dev()
  * allocates and inits the device structs, registers i2c bus and v4l device
  */
-static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
                           struct usb_interface *interface,
                           int minor)
 {
-       struct em28xx *dev = *devhandle;
        int retval;
 
        dev->udev = udev;
@@ -2931,7 +3015,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
 
        if (!dev->board.is_em2800) {
                /* Resets I2C speed */
-               em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+               retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
                if (retval < 0) {
                        em28xx_errdev("%s: em28xx_write_reg failed!"
                                      " retval [%d]\n",
@@ -3031,12 +3115,11 @@ unregister_dev:
 static int em28xx_usb_probe(struct usb_interface *interface,
                            const struct usb_device_id *id)
 {
-       const struct usb_endpoint_descriptor *endpoint;
        struct usb_device *udev;
        struct em28xx *dev = NULL;
        int retval;
-       bool is_audio_only = false, has_audio = false;
-       int i, nr, isoc_pipe;
+       bool has_audio = false, has_video = false, has_dvb = false;
+       int i, nr;
        const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
        char *speed;
        char descr[255] = "";
@@ -3068,54 +3151,65 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                goto err;
        }
 
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               em28xx_err(DRIVER_NAME ": out of memory!\n");
+               retval = -ENOMEM;
+               goto err;
+       }
+
+       /* compute alternate max packet sizes */
+       dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) *
+                                       interface->num_altsetting, GFP_KERNEL);
+       if (dev->alt_max_pkt_size == NULL) {
+               em28xx_errdev("out of memory!\n");
+               kfree(dev);
+               retval = -ENOMEM;
+               goto err;
+       }
+
        /* Get endpoints */
        for (i = 0; i < interface->num_altsetting; i++) {
                int ep;
 
                for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
-                       struct usb_host_endpoint        *e;
-                       e = &interface->altsetting[i].endpoint[ep];
-
-                       if (e->desc.bEndpointAddress == 0x83)
-                               has_audio = true;
+                       const struct usb_endpoint_descriptor *e;
+                       int sizedescr, size;
+
+                       e = &interface->altsetting[i].endpoint[ep].desc;
+
+                       sizedescr = le16_to_cpu(e->wMaxPacketSize);
+                       size = sizedescr & 0x7ff;
+
+                       if (udev->speed == USB_SPEED_HIGH)
+                               size = size * hb_mult(sizedescr);
+
+                       if (usb_endpoint_xfer_isoc(e) &&
+                           usb_endpoint_dir_in(e)) {
+                               switch (e->bEndpointAddress) {
+                               case EM28XX_EP_AUDIO:
+                                       has_audio = true;
+                                       break;
+                               case EM28XX_EP_ANALOG:
+                                       has_video = true;
+                                       dev->alt_max_pkt_size[i] = size;
+                                       break;
+                               case EM28XX_EP_DIGITAL:
+                                       has_dvb = true;
+                                       if (size > dev->dvb_max_pkt_size) {
+                                               dev->dvb_max_pkt_size = size;
+                                               dev->dvb_alt = i;
+                                       }
+                                       break;
+                               }
+                       }
                }
        }
 
-       endpoint = &interface->cur_altsetting->endpoint[0].desc;
-
-       /* check if the device has the iso in endpoint at the correct place */
-       if (usb_endpoint_xfer_isoc(endpoint)
-           &&
-           (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) {
-               /* It's a newer em2874/em2875 device */
-               isoc_pipe = 0;
-       } else {
-               int check_interface = 1;
-               isoc_pipe = 1;
-               endpoint = &interface->cur_altsetting->endpoint[1].desc;
-               if (!usb_endpoint_xfer_isoc(endpoint))
-                       check_interface = 0;
-
-               if (usb_endpoint_dir_out(endpoint))
-                       check_interface = 0;
-
-               if (!check_interface) {
-                       if (has_audio) {
-                               is_audio_only = true;
-                       } else {
-                               em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
-                                       "interface %i, class %i found.\n",
-                                       le16_to_cpu(udev->descriptor.idVendor),
-                                       le16_to_cpu(udev->descriptor.idProduct),
-                                       ifnum,
-                                       interface->altsetting[0].desc.bInterfaceClass);
-                               em28xx_err(DRIVER_NAME " This is an anciliary "
-                                       "interface not used by the driver\n");
-
-                               retval = -ENODEV;
-                               goto err;
-                       }
-               }
+       if (!(has_audio || has_video || has_dvb)) {
+               retval = -ENODEV;
+               goto err_free;
        }
 
        switch (udev->speed) {
@@ -3141,6 +3235,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                        strlcat(descr, " ", sizeof(descr));
                strlcat(descr, udev->product, sizeof(descr));
        }
+
        if (*descr)
                strlcat(descr, " ", sizeof(descr));
 
@@ -3157,6 +3252,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                printk(KERN_INFO DRIVER_NAME
                       ": Audio Vendor Class interface %i found\n",
                       ifnum);
+       if (has_video)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Video interface %i found\n",
+                      ifnum);
+       if (has_dvb)
+               printk(KERN_INFO DRIVER_NAME
+                      ": DVB interface %i found\n",
+                      ifnum);
 
        /*
         * Make sure we have 480 Mbps of bandwidth, otherwise things like
@@ -3168,22 +3271,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                printk(DRIVER_NAME ": Device must be connected to a high-speed"
                       " USB 2.0 port.\n");
                retval = -ENODEV;
-               goto err;
-       }
-
-       /* allocate memory for our device state and initialize it */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               em28xx_err(DRIVER_NAME ": out of memory!\n");
-               retval = -ENOMEM;
-               goto err;
+               goto err_free;
        }
 
        snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
        dev->devno = nr;
        dev->model = id->driver_info;
        dev->alt   = -1;
-       dev->is_audio_only = is_audio_only;
+       dev->is_audio_only = has_audio && !(has_video || has_dvb);
        dev->has_alsa_audio = has_audio;
        dev->audio_ifnum = ifnum;
 
@@ -3196,26 +3291,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                }
        }
 
-       /* compute alternate max packet sizes */
        dev->num_alt = interface->num_altsetting;
-       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");
-               kfree(dev);
-               retval = -ENOMEM;
-               goto err;
-       }
-
-       for (i = 0; i < dev->num_alt ; i++) {
-               u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
-               unsigned int size = tmp & 0x7ff;
-
-               if (udev->speed == USB_SPEED_HIGH)
-                       size = size * hb_mult(tmp);
-
-               dev->alt_max_pkt_size[i] = size;
-       }
 
        if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
                dev->model = card[nr];
@@ -3226,12 +3302,9 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        /* allocate device struct */
        mutex_init(&dev->lock);
        mutex_lock(&dev->lock);
-       retval = em28xx_init_dev(&dev, udev, interface, nr);
+       retval = em28xx_init_dev(dev, udev, interface, nr);
        if (retval) {
-               mutex_unlock(&dev->lock);
-               kfree(dev->alt_max_pkt_size);
-               kfree(dev);
-               goto err;
+               goto unlock_and_free;
        }
 
        request_modules(dev);
@@ -3250,6 +3323,13 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 
        return 0;
 
+unlock_and_free:
+       mutex_unlock(&dev->lock);
+
+err_free:
+       kfree(dev->alt_max_pkt_size);
+       kfree(dev);
+
 err:
        clear_bit(nr, &em28xx_devused);
 
index 804a4ab47ac636405579d4d6a8003dcffafa04f0..0aacc96f9a232416928e8a07346620f223ef0cbc 100644 (file)
@@ -568,7 +568,7 @@ int em28xx_audio_setup(struct em28xx *dev)
        em28xx_warn("AC97 features = 0x%04x\n", feat);
 
        /* Try to identify what audio processor we have */
-       if ((vid == 0xffffffff) && (feat == 0x6a90))
+       if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
                dev->audio_mode.ac97 = EM28XX_AC97_EM202;
        else if ((vid >> 8) == 0x838476)
                dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL;
@@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
                        should also be using 'desc.bInterval'
                 */
                pipe = usb_rcvisocpipe(dev->udev,
-                       dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
+                                      dev->mode == EM28XX_ANALOG_MODE ?
+                                      EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
 
                usb_fill_int_urb(urb, dev->udev, pipe,
                                 dev->isoc_ctl.transfer_buffer[i], sb_size,
@@ -1108,62 +1109,6 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
 }
 EXPORT_SYMBOL_GPL(em28xx_init_isoc);
 
-/* Determine the packet size for the DVB stream for the given device
-   (underlying value programmed into the eeprom) */
-int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
-{
-       unsigned int chip_cfg2;
-       unsigned int packet_size;
-
-       switch (dev->chip_id) {
-       case CHIP_ID_EM2710:
-       case CHIP_ID_EM2750:
-       case CHIP_ID_EM2800:
-       case CHIP_ID_EM2820:
-       case CHIP_ID_EM2840:
-       case CHIP_ID_EM2860:
-               /* No DVB support */
-               return -EINVAL;
-       case CHIP_ID_EM2870:
-       case CHIP_ID_EM2883:
-               /* TS max packet size stored in bits 1-0 of R01 */
-               chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
-               switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
-               case EM28XX_CHIPCFG2_TS_PACKETSIZE_188:
-                       packet_size = 188;
-                       break;
-               case EM28XX_CHIPCFG2_TS_PACKETSIZE_376:
-                       packet_size = 376;
-                       break;
-               case EM28XX_CHIPCFG2_TS_PACKETSIZE_564:
-                       packet_size = 564;
-                       break;
-               case EM28XX_CHIPCFG2_TS_PACKETSIZE_752:
-                       packet_size = 752;
-                       break;
-               }
-               break;
-       case CHIP_ID_EM2874:
-               /*
-                * FIXME: for now assumes 564 like it was before, but the
-                * em2874 code should be added to return the proper value
-                */
-               packet_size = 564;
-               break;
-       case CHIP_ID_EM2884:
-       case CHIP_ID_EM28174:
-       default:
-               /*
-                * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T
-                * but not enough for 44 Mbit DVB-C.
-                */
-               packet_size = 752;
-       }
-
-       return packet_size;
-}
-EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
-
 /*
  * em28xx_wake_i2c()
  * configure i2c attached devices
index cef7a2d409cbc27c53c2aabe805528d62f40b894..9449423098e0d4163eabe8d7a0b0c57cdb484cc2 100644 (file)
@@ -44,6 +44,7 @@
 #include "drxk.h"
 #include "tda10071.h"
 #include "a8293.h"
+#include "qt1010.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -163,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb)
        struct em28xx *dev = dvb->adapter.priv;
        int max_dvb_packet_size;
 
-       usb_set_interface(dev->udev, 0, 1);
+       usb_set_interface(dev->udev, 0, dev->dvb_alt);
        rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        if (rc < 0)
                return rc;
 
-       max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+       max_dvb_packet_size = dev->dvb_max_pkt_size;
        if (max_dvb_packet_size < 0)
                return max_dvb_packet_size;
        dprintk(1, "Using %d buffers each with %d bytes\n",
@@ -302,10 +303,12 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
 };
 
 static struct drxd_config em28xx_drxd = {
-       .index = 0, .demod_address = 0x70, .demod_revision = 0xa2,
-       .demoda_address = 0x00, .pll_address = 0x00,
-       .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1,
-       .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000,
+       .demod_address = 0x70,
+       .demod_revision = 0xa2,
+       .pll_type = DRXD_PLL_NONE,
+       .clock = 12000,
+       .insert_rs_byte = 1,
+       .IF = 42800000,
        .disable_i2c_gate_ctrl = 1,
 };
 
@@ -316,6 +319,14 @@ struct drxk_config terratec_h5_drxk = {
        .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
 };
 
+struct drxk_config hauppauge_930c_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+       .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
+       .chunk_size = 56,
+};
+
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct em28xx_dvb *dvb = fe->sec_priv;
@@ -334,6 +345,73 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
        return status;
 }
 
+static void hauppauge_hvr930c_init(struct em28xx *dev)
+{
+       int i;
+
+       struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
+               {EM2874_R80_GPIO,       0xff,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xfb,   0xff,   0x32},
+               {EM2874_R80_GPIO,       0xff,   0xff,   0xb8},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
+               {EM2874_R80_GPIO,       0xaf,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x76},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x40},
+
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
+
+               { -1,                   -1,     -1,     -1},
+       };
+
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+               {{ 0x04, 0x00 }, 2},
+               {{ 0x00, 0x04 }, 2},
+               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+               {{ 0x04, 0x14 }, 2},
+               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+       };
+
+       em28xx_gpio_set(dev, hauppauge_hvr930c_init);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+       em28xx_gpio_set(dev, hauppauge_hvr930c_end);
+
+       msleep(100);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(30);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+       msleep(10);
+
+}
+
 static void terratec_h5_init(struct em28xx *dev)
 {
        int i;
@@ -425,13 +503,6 @@ static struct tda10023_config em28xx_tda10023_config = {
 static struct cxd2820r_config em28xx_cxd2820r_config = {
        .i2c_address = (0xd8 >> 1),
        .ts_mode = CXD2820R_TS_SERIAL,
-       .if_dvbt_6  = 3300,
-       .if_dvbt_7  = 3500,
-       .if_dvbt_8  = 4000,
-       .if_dvbt2_6 = 3300,
-       .if_dvbt2_7 = 3500,
-       .if_dvbt2_8 = 4000,
-       .if_dvbc    = 5000,
 
        /* enable LNA for DVB-T2 and DVB-C */
        .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
@@ -456,6 +527,17 @@ static const struct a8293_config em28xx_a8293_config = {
        .i2c_addr = 0x08, /* (0x10 >> 1) */
 };
 
+static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
+       .demod_address = (0x1e >> 1),
+       .disable_i2c_gate_ctrl = 1,
+       .no_tuner = 1,
+       .parallel_ts = 1,
+};
+static struct qt1010_config em28xx_qt1010_config = {
+       .i2c_address = 0x62
+
+};
+
 /* ------------------------------------------------------------------ */
 
 static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
@@ -708,6 +790,14 @@ static int em28xx_dvb_init(struct em28xx *dev)
                        goto out_free;
                }
                break;
+       case EM2870_BOARD_KWORLD_355U:
+               dvb->fe[0] = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_no_i2c_gate_dev,
+                                          &dev->i2c_adap);
+               if (dvb->fe[0] != NULL)
+                       dvb_attach(qt1010_attach, dvb->fe[0],
+                                  &dev->i2c_adap, &em28xx_qt1010_config);
+               break;
        case EM2883_BOARD_KWORLD_HYBRID_330U:
        case EM2882_BOARD_EVGA_INDTUBE:
                dvb->fe[0] = dvb_attach(s5h1409_attach,
@@ -761,50 +851,72 @@ static int em28xx_dvb_init(struct em28xx *dev)
                                   &dev->i2c_adap, &kworld_a340_config);
                break;
        case EM28174_BOARD_PCTV_290E:
-               /* MFE
-                * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */
-               /* FE 0 */
                dvb->fe[0] = dvb_attach(cxd2820r_attach,
-                       &em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
+                                       &em28xx_cxd2820r_config,
+                                       &dev->i2c_adap,
+                                       NULL);
                if (dvb->fe[0]) {
                        /* FE 0 attach tuner */
-                       if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-                               &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
+                       if (!dvb_attach(tda18271_attach,
+                                       dvb->fe[0],
+                                       0x60,
+                                       &dev->i2c_adap,
+                                       &em28xx_cxd2820r_tda18271_config)) {
+
                                dvb_frontend_detach(dvb->fe[0]);
                                result = -EINVAL;
                                goto out_free;
                        }
-                       /* FE 1. This dvb_attach() cannot fail. */
-                       dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL,
-                               dvb->fe[0]);
-                       dvb->fe[1]->id = 1;
-                       /* FE 1 attach tuner */
-                       if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
-                               &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
-                               dvb_frontend_detach(dvb->fe[1]);
-                               /* leave FE 0 still active */
-                       }
+               }
+               break;
+       case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
+       {
+               struct xc5000_config cfg;
+               hauppauge_hvr930c_init(dev);
+
+               dvb->fe[0] = dvb_attach(drxk_attach,
+                                       &hauppauge_930c_drxk, &dev->i2c_adap);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               /* FIXME: do we need a pll semaphore? */
+               dvb->fe[0]->sec_priv = dvb;
+               sema_init(&dvb->pll_mutex, 1);
+               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
 
-                       mfe_shared = 1;
+               /* Attach xc5000 */
+               memset(&cfg, 0, sizeof(cfg));
+               cfg.i2c_address  = 0x61;
+               cfg.if_khz = 4000;
+
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+               if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
+                               &cfg)) {
+                       result = -EINVAL;
+                       goto out_free;
                }
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
                break;
+       }
        case EM2884_BOARD_TERRATEC_H5:
+       case EM2884_BOARD_CINERGY_HTC_STICK:
                terratec_h5_init(dev);
 
-               dvb->dont_attach_fe1 = 1;
-
-               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]);
+               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
                if (!dvb->fe[0]) {
                        result = -EINVAL;
                        goto out_free;
                }
-
                /* FIXME: do we need a pll semaphore? */
                dvb->fe[0]->sec_priv = dvb;
                sema_init(&dvb->pll_mutex, 1);
                dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
                dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-               dvb->fe[1]->id = 1;
 
                /* Attach tda18271 to DVB-C frontend */
                if (dvb->fe[0]->ops.i2c_gate_ctrl)
@@ -816,12 +928,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
                if (dvb->fe[0]->ops.i2c_gate_ctrl)
                        dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
 
-               /* Hack - needed by drxk/tda18271c2dd */
-               dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv;
-               memcpy(&dvb->fe[1]->ops.tuner_ops,
-                      &dvb->fe[0]->ops.tuner_ops,
-                      sizeof(dvb->fe[0]->ops.tuner_ops));
-
                break;
        case EM28174_BOARD_PCTV_460E:
                /* attach demod */
@@ -845,6 +951,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
        }
        /* define general-purpose callback pointer */
        dvb->fe[0]->callback = em28xx_tuner_callback;
+       if (dvb->fe[1])
+               dvb->fe[1]->callback = em28xx_tuner_callback;
 
        /* register everything */
        result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
index 679da480428113ec8d7da347e722bf36bde6e590..2630b265b0e813c5c6f450927367d3899933c013 100644 (file)
@@ -306,7 +306,8 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
                                   poll_result.rc_data[0],
                                   poll_result.toggle_bit);
 
-               if (ir->dev->chip_id == CHIP_ID_EM2874)
+               if (ir->dev->chip_id == CHIP_ID_EM2874 ||
+                   ir->dev->chip_id == CHIP_ID_EM2884)
                        /* The em2874 clears the readcount field every time the
                           register is read.  The em2860/2880 datasheet says that it
                           is supposed to clear the readcount, but it doesn't.  So with
@@ -371,13 +372,15 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
        case CHIP_ID_EM2883:
                ir->get_key = default_polling_getkey;
                break;
+       case CHIP_ID_EM2884:
        case CHIP_ID_EM2874:
        case CHIP_ID_EM28174:
                ir->get_key = em2874_polling_getkey;
                em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
                break;
        default:
-               printk("Unrecognized em28xx chip id: IR not supported\n");
+               printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
+                       dev->chip_id);
                rc = -EINVAL;
        }
 
index 66f792361b97dee12d7b91c9839c12f71600f8a2..2f626850572643a18e6f5c79d41468f893fade2e 100644 (file)
 #define EM_GPO_2   (1 << 2)
 #define EM_GPO_3   (1 << 3)
 
+/* em28xx endpoints */
+#define EM28XX_EP_ANALOG       0x82
+#define EM28XX_EP_AUDIO                0x83
+#define EM28XX_EP_DIGITAL      0x84
+
 /* em2800 registers */
 #define EM2800_R08_AUDIOSRC 0x08
 
index 9b4557a2f6d02858cb0c6a29a4295fac966cd317..613300b51a9e82012f17c664ad7ae2d90ca70a03 100644 (file)
@@ -1070,6 +1070,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                /* the em2800 can only scale down to 50% */
                height = height > (3 * maxh / 4) ? maxh : maxh / 2;
                width = width > (3 * maxw / 4) ? maxw : maxw / 2;
+                /* MaxPacketSize for em2800 is too small to capture at full resolution
+                 * use half of maxw as the scaler can only scale to 50% */
+               if (width == maxw && height == maxh)
+                       width /= 2;
        } else {
                /* width must even because of the YUYV format
                   height must be even because of interlacing */
@@ -2503,6 +2507,7 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 {
       u8 val;
        int ret;
+       unsigned int maxw;
 
        printk(KERN_INFO "%s: v4l2 driver version %s\n",
                dev->name, EM28XX_VERSION);
@@ -2515,8 +2520,15 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 
        /* Analog specific initialization */
        dev->format = &format[0];
+
+       maxw = norm_maxw(dev);
+        /* MaxPacketSize for em2800 is too small to capture at full resolution
+         * use half of maxw as the scaler can only scale to 50% */
+        if (dev->board.is_em2800)
+            maxw /= 2;
+
        em28xx_set_video_format(dev, format[0].fourcc,
-                               norm_maxw(dev), norm_maxh(dev));
+                               maxw, norm_maxh(dev));
 
        video_mux(dev, dev->ctl_input);
 
index 2a2cb7ed0014fcda319a31c60066c3ebbfa12f9f..22e252bcc41e2fffc0ad5ef9bcd08fca24b82175 100644 (file)
@@ -38,6 +38,7 @@
 #include <media/videobuf-dvb.h>
 #endif
 #include "tuner-xc2028.h"
+#include "xc5000.h"
 #include "em28xx-reg.h"
 
 /* Boards supported by driver */
 #define EM28174_BOARD_PCTV_290E                   78
 #define EM2884_BOARD_TERRATEC_H5                 79
 #define EM28174_BOARD_PCTV_460E                   80
+#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C    81
+#define EM2884_BOARD_CINERGY_HTC_STICK           82
+#define EM2860_BOARD_HT_VIDBOX_NW03              83
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -594,6 +598,8 @@ struct em28xx {
        int max_pkt_size;       /* max packet size of isoc transaction */
        int num_alt;            /* Number of alternative settings */
        unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       int dvb_alt;                            /* alternate for DVB */
+       unsigned int dvb_max_pkt_size;          /* wMaxPacketSize for DVB */
        struct urb *urb[EM28XX_NUM_BUFS];       /* urb for isoc transfers */
        char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc
                                                   transfer */
@@ -825,7 +831,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev)
        if (dev->board.is_webcam)
                return dev->sensor_xres;
 
-       if (dev->board.max_range_640_480 || dev->board.is_em2800)
+       if (dev->board.max_range_640_480)
                return 640;
 
        return 720;
index 27cb197d0bd6e911696750e988a85e5af0a5994f..27e3e0c0b219138a689909203d9ebf3fa354ea12 100644 (file)
@@ -1661,18 +1661,7 @@ static struct platform_driver viu_of_platform_driver = {
        },
 };
 
-static int __init viu_init(void)
-{
-       return platform_driver_register(&viu_of_platform_driver);
-}
-
-static void __exit viu_exit(void)
-{
-       platform_driver_unregister(&viu_of_platform_driver);
-}
-
-module_init(viu_init);
-module_exit(viu_exit);
+module_platform_driver(viu_of_platform_driver);
 
 MODULE_DESCRIPTION("Freescale Video-In(VIU)");
 MODULE_AUTHOR("Hongjun Chen");
index 103af3fe5aa07b8aabd5cbd1acb3c8fa08ca6c82..dfe268bfa4f8f55a1e18139515546cd45365eb93 100644 (file)
@@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ
          To compile this driver as a module, choose M here: the
          module will be called gspca_jeilinj.
 
+config USB_GSPCA_JL2005BCD
+       tristate "JL2005B/C/D USB V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based the
+         JL2005B, JL2005C, or JL2005D chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_jl2005bcd.
+
 config USB_GSPCA_KINECT
        tristate "Kinect sensor device USB Camera Driver"
        depends on VIDEO_V4L2 && USB_GSPCA
index f345f494d0f3121e16302ee20d61daea8d813deb..79ebe46e1ad792b80d3a013aa9efba786ea82d9f 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1)    += gspca_cpia1.o
 obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
 obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
 obj-$(CONFIG_USB_GSPCA_JEILINJ)  += gspca_jeilinj.o
+obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
 obj-$(CONFIG_USB_GSPCA_KINECT)   += gspca_kinect.o
 obj-$(CONFIG_USB_GSPCA_KONICA)   += gspca_konica.o
 obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
@@ -49,6 +50,7 @@ gspca_cpia1-objs    := cpia1.o
 gspca_etoms-objs    := etoms.o
 gspca_finepix-objs  := finepix.o
 gspca_jeilinj-objs  := jeilinj.o
+gspca_jl2005bcd-objs  := jl2005bcd.o
 gspca_kinect-objs   := kinect.o
 gspca_konica-objs   := konica.o
 gspca_mars-objs     := mars.o
index 636627b57dc933ff447c1f2485ae031e173bdb74..9769f17915c0546c41391025addcaa942b12a68d 100644 (file)
@@ -76,7 +76,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        gspca_dev->cam.cam_mode = vga_mode;
        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
        gspca_dev->cam.no_urb_create = 1;
-       gspca_dev->cam.reverse_alts = 1;
        return 0;
 }
 
@@ -135,13 +134,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
+       struct usb_interface *intf;
+
        reg_w(gspca_dev, 0x003c, 0x0003);
        reg_w(gspca_dev, 0x003c, 0x0004);
        reg_w(gspca_dev, 0x003c, 0x0005);
        reg_w(gspca_dev, 0x003c, 0x0006);
        reg_w(gspca_dev, 0x003c, 0x0007);
+
+       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
        usb_set_interface(gspca_dev->dev, gspca_dev->iface,
-                                       gspca_dev->nbalt - 1);
+                                       intf->num_altsetting - 1);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
index a8f54c20e58550d0426b5a712b9d10ff1c0f38b5..c84e26006fc386afef472a7a09fa52e4a6b572d5 100644 (file)
@@ -337,7 +337,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
                return -1;
 
        cam = &gspca_dev->cam;
-       gspca_dev->nbalt = 4;
 
        switch (sd->sensor) {
        case ID_MI1320:
index 2ca10dfec91fd2347532d35e22ea44fd4ee01298..ca5a2b139d0b739f8d5aa149785d95c60d674a4a 100644 (file)
@@ -633,23 +633,32 @@ static u32 which_bandwidth(struct gspca_dev *gspca_dev)
        u32 bandwidth;
        int i;
 
+       /* get the (max) image size */
        i = gspca_dev->curr_mode;
        bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
 
-       /* if the image is compressed, estimate the mean image size */
-       if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+       /* if the image is compressed, estimate its mean size */
+       if (!gspca_dev->cam.needs_full_bandwidth &&
+           bandwidth < gspca_dev->cam.cam_mode[i].width *
                                gspca_dev->cam.cam_mode[i].height)
-               bandwidth /= 3;
+               bandwidth = bandwidth * 3 / 8;  /* 0.375 */
 
        /* estimate the frame rate */
        if (gspca_dev->sd_desc->get_streamparm) {
                struct v4l2_streamparm parm;
 
-               parm.parm.capture.timeperframe.denominator = 15;
                gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
                bandwidth *= parm.parm.capture.timeperframe.denominator;
+               bandwidth /= parm.parm.capture.timeperframe.numerator;
        } else {
-               bandwidth *= 15;                /* 15 fps */
+
+               /* don't hope more than 15 fps with USB 1.1 and
+                * image resolution >= 640x480 */
+               if (gspca_dev->width >= 640
+                && gspca_dev->dev->speed == USB_SPEED_FULL)
+                       bandwidth *= 15;                /* 15 fps */
+               else
+                       bandwidth *= 30;                /* 30 fps */
        }
 
        PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
@@ -667,9 +676,8 @@ struct ep_tb_s {
  * build the table of the endpoints
  * and compute the minimum bandwidth for the image transfer
  */
-static int build_ep_tb(struct gspca_dev *gspca_dev,
+static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
                        struct usb_interface *intf,
-                       int xfer,
                        struct ep_tb_s *ep_tb)
 {
        struct usb_host_endpoint *ep;
@@ -687,17 +695,21 @@ static int build_ep_tb(struct gspca_dev *gspca_dev,
                ep_tb->bandwidth = 2000 * 2000 * 120;
                found = 0;
                for (j = 0; j < nbalt; j++) {
-                       ep = alt_xfer(&intf->altsetting[j], xfer);
+                       ep = alt_xfer(&intf->altsetting[j],
+                                     USB_ENDPOINT_XFER_ISOC);
                        if (ep == NULL)
                                continue;
+                       if (ep->desc.bInterval == 0) {
+                               pr_err("alt %d iso endp with 0 interval\n", j);
+                               continue;
+                       }
                        psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-                       if (!gspca_dev->cam.bulk)               /* isoc */
-                               psize = (psize & 0x07ff) *
-                                               (1 + ((psize >> 11) & 3));
-                       bandwidth = psize * ep->desc.bInterval * 1000;
+                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+                       bandwidth = psize * 1000;
                        if (gspca_dev->dev->speed == USB_SPEED_HIGH
                         || gspca_dev->dev->speed == USB_SPEED_SUPER)
                                bandwidth *= 8;
+                       bandwidth /= 1 << (ep->desc.bInterval - 1);
                        if (bandwidth <= last_bw)
                                continue;
                        if (bandwidth < ep_tb->bandwidth) {
@@ -715,6 +727,23 @@ static int build_ep_tb(struct gspca_dev *gspca_dev,
                ep_tb++;
        }
 
+       /*
+        * If the camera:
+        * has a usb audio class interface (a built in usb mic); and
+        * is a usb 1 full speed device; and
+        * uses the max full speed iso bandwidth; and
+        * and has more than 1 alt setting
+        * then skip the highest alt setting to spare bandwidth for the mic
+        */
+       if (gspca_dev->audio &&
+                       gspca_dev->dev->speed == USB_SPEED_FULL &&
+                       last_bw >= 1000000 &&
+                       i > 1) {
+               PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt");
+               i--;
+               ep_tb--;
+       }
+
        /* get the requested bandwidth and start at the highest atlsetting */
        bandwidth = which_bandwidth(gspca_dev);
        ep_tb--;
@@ -790,10 +819,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
                                                    ep->desc.bEndpointAddress);
                        urb->transfer_flags = URB_ISO_ASAP
                                        | URB_NO_TRANSFER_DMA_MAP;
-                       if (gspca_dev->dev->speed == USB_SPEED_LOW)
-                               urb->interval = ep->desc.bInterval;
-                       else
-                               urb->interval = 1 << (ep->desc.bInterval - 1);
+                       urb->interval = 1 << (ep->desc.bInterval - 1);
                        urb->complete = isoc_irq;
                        urb->number_of_packets = npkt;
                        for (i = 0; i < npkt; i++) {
@@ -848,7 +874,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
        xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
                                   : USB_ENDPOINT_XFER_ISOC;
 
-       /* if the subdriver forced an altsetting, get the endpoint */
+       /* if bulk or the subdriver forced an altsetting, get the endpoint */
        if (gspca_dev->alt != 0) {
                gspca_dev->alt--;       /* (previous version compatibility) */
                ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
@@ -863,7 +889,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 
        /* else, compute the minimum bandwidth
         * and build the endpoint table */
-               alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+               alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb);
                if (alt_idx <= 0) {
                        pr_err("no transfer endpoint found\n");
                        ret = -EIO;
@@ -880,7 +906,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
        for (;;) {
                if (alt != gspca_dev->alt) {
                        alt = gspca_dev->alt;
-                       if (gspca_dev->nbalt > 1) {
+                       if (intf->num_altsetting > 1) {
                                ret = usb_set_interface(gspca_dev->dev,
                                                        gspca_dev->iface,
                                                        alt);
@@ -2300,15 +2326,14 @@ int gspca_dev_probe2(struct usb_interface *intf,
        }
        gspca_dev->dev = dev;
        gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
-       gspca_dev->nbalt = intf->num_altsetting;
 
        /* check if any audio device */
-       if (dev->config->desc.bNumInterfaces != 1) {
+       if (dev->actconfig->desc.bNumInterfaces != 1) {
                int i;
                struct usb_interface *intf2;
 
-               for (i = 0; i < dev->config->desc.bNumInterfaces; i++) {
-                       intf2 = dev->config->interface[i];
+               for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+                       intf2 = dev->actconfig->interface[i];
                        if (intf2 != NULL
                         && intf2->altsetting != NULL
                         && intf2->altsetting->desc.bInterfaceClass ==
@@ -2389,7 +2414,7 @@ int gspca_dev_probe(struct usb_interface *intf,
        }
 
        /* the USB video interface must be the first one */
-       if (dev->config->desc.bNumInterfaces != 1
+       if (dev->actconfig->desc.bNumInterfaces != 1
         && intf->cur_altsetting->desc.bInterfaceNumber != 0)
                return -ENODEV;
 
index e444f16e14971c97d02d63e13d74fe57c4fc32ee..589009f4496fcfc2599bed9709f214cc082780f3 100644 (file)
@@ -69,7 +69,9 @@ struct cam {
        u8 bulk;                /* image transfer by 0:isoc / 1:bulk */
        u8 npkt;                /* number of packets in an ISOC message
                                 * 0 is the default value: 32 packets */
-       u8 reverse_alts;        /* Alt settings are in high to low order */
+       u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc.
+                                * code that the cam fills all image buffers to
+                                * the max, even when using compression. */
 };
 
 struct gspca_dev;
@@ -208,7 +210,6 @@ struct gspca_dev {
        char memory;                    /* memory type (V4L2_MEMORY_xxx) */
        __u8 iface;                     /* USB interface number */
        __u8 alt;                       /* USB alternate setting */
-       __u8 nbalt;                     /* number of USB alternate settings */
        u8 audio;                       /* presence of audio device */
 };
 
diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c
new file mode 100644 (file)
index 0000000..53f58ef
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * Jeilin JL2005B/C/D library
+ *
+ * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * 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
+ * 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
+ */
+
+#define MODULE_NAME "jl2005bcd"
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define JL2005C_CMD_TIMEOUT 500
+#define JL2005C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define JL2005C_MAX_TRANSFER 0x200
+#define FRAME_HEADER_LEN 16
+
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;  /* !! must be the first item */
+       unsigned char firmware_id[6];
+       const struct v4l2_pix_format *cap_mode;
+       /* Driver stuff */
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+       u8 frame_brightness;
+       int block_size; /* block size of camera */
+       int vga;        /* 1 if vga cam, 0 if cif cam */
+};
+
+
+/* Camera has two resolution settings. What they are depends on model. */
+static const struct v4l2_pix_format cif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/*
+ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
+ * and 0x82 for bulk data transfer.
+ */
+
+/* All commands are two bytes only */
+static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
+{
+       int retval;
+
+       memcpy(gspca_dev->usb_buf, command, 2);
+       retval = usb_bulk_msg(gspca_dev->dev,
+                       usb_sndbulkpipe(gspca_dev->dev, 3),
+                       gspca_dev->usb_buf, 2, NULL, 500);
+       if (retval < 0)
+               pr_err("command write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+       return retval;
+}
+
+/* Response to a command is one byte in usb_buf[0], only if requested. */
+static int jl2005c_read1(struct gspca_dev *gspca_dev)
+{
+       int retval;
+
+       retval = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x84),
+                               gspca_dev->usb_buf, 1, NULL, 500);
+       if (retval < 0)
+               pr_err("read command [0x%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+       return retval;
+}
+
+/* Response appears in gspca_dev->usb_buf[0] */
+static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
+{
+       int retval;
+
+       static u8 instruction[2] = {0x95, 0x00};
+       /* put register to read in byte 1 */
+       instruction[1] = reg;
+       /* Send the read request */
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+               return retval;
+       retval = jl2005c_read1(gspca_dev);
+
+       return retval;
+}
+
+static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval;
+       int frame_brightness = 0;
+
+       static u8 instruction[2] = {0x7f, 0x01};
+
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+               return retval;
+
+       i = 0;
+       while (i < 20 && !frame_brightness) {
+               /* If we tried 20 times, give up. */
+               retval = jl2005c_read_reg(gspca_dev, 0x7e);
+               if (retval < 0)
+                       return retval;
+               frame_brightness = gspca_dev->usb_buf[0];
+               retval = jl2005c_read_reg(gspca_dev, 0x7d);
+               if (retval < 0)
+                       return retval;
+               i++;
+       }
+       PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
+       return retval;
+}
+
+static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
+                                                   unsigned char value)
+{
+       int retval;
+       u8 instruction[2];
+
+       instruction[0] = reg;
+       instruction[1] = value;
+
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+                       return retval;
+
+       return retval;
+}
+
+static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int i = 0;
+       int retval = -1;
+       unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
+
+       PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
+       /* Read the first ID byte once for warmup */
+       retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
+       PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
+       if (retval < 0)
+               return retval;
+       /* Now actually get the ID string */
+       for (i = 0; i < 6; i++) {
+               retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
+               if (retval < 0)
+                       return retval;
+               sd->firmware_id[i] = gspca_dev->usb_buf[0];
+       }
+       PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
+                                               sd->firmware_id[0],
+                                               sd->firmware_id[1],
+                                               sd->firmware_id[2],
+                                               sd->firmware_id[3],
+                                               sd->firmware_id[4],
+                                               sd->firmware_id[5]);
+       return 0;
+}
+
+static int jl2005c_stream_start_vga_lg
+                   (struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x05, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x18},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x52},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x06, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x1a},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x52},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x05, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x30},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x42},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x06, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x32},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x42},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+
+static int jl2005c_stop(struct gspca_dev *gspca_dev)
+{
+       int retval;
+
+       retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
+       return retval;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+static void jl2005c_dostream(struct work_struct *work)
+{
+       struct sd *dev = container_of(work, struct sd, work_struct);
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+       int bytes_left = 0; /* bytes remaining in current frame. */
+       int data_len;   /* size to use for the next read. */
+       int header_read = 0;
+       unsigned char header_sig[2] = {0x4a, 0x4c};
+       int act_len;
+       int packet_type;
+       int ret;
+       u8 *buffer;
+
+       buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+       if (!buffer) {
+               pr_err("Couldn't allocate USB buffer\n");
+               goto quit_stream;
+       }
+
+       while (gspca_dev->present && gspca_dev->streaming) {
+               /* Check if this is a new frame. If so, start the frame first */
+               if (!header_read) {
+                       mutex_lock(&gspca_dev->usb_lock);
+                       ret = jl2005c_start_new_frame(gspca_dev);
+                       mutex_unlock(&gspca_dev->usb_lock);
+                       if (ret < 0)
+                               goto quit_stream;
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+                               buffer, JL2005C_MAX_TRANSFER, &act_len,
+                               JL2005C_DATA_TIMEOUT);
+                       PDEBUG(D_PACK,
+                               "Got %d bytes out of %d for header",
+                                       act_len, JL2005C_MAX_TRANSFER);
+                       if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
+                               goto quit_stream;
+                       /* Check whether we actually got the first blodk */
+                       if (memcmp(header_sig, buffer, 2) != 0) {
+                               pr_err("First block is not the first block\n");
+                               goto quit_stream;
+                       }
+                       /* total size to fetch is byte 7, times blocksize
+                        * of which we already got act_len */
+                       bytes_left = buffer[0x07] * dev->block_size - act_len;
+                       PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
+                       /* We keep the header. It has other information, too.*/
+                       packet_type = FIRST_PACKET;
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       buffer, act_len);
+                       header_read = 1;
+               }
+               while (bytes_left > 0 && gspca_dev->present) {
+                       data_len = bytes_left > JL2005C_MAX_TRANSFER ?
+                               JL2005C_MAX_TRANSFER : bytes_left;
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+                               buffer, data_len, &act_len,
+                               JL2005C_DATA_TIMEOUT);
+                       if (ret < 0 || act_len < data_len)
+                               goto quit_stream;
+                       PDEBUG(D_PACK,
+                               "Got %d bytes out of %d for frame",
+                                               data_len, bytes_left);
+                       bytes_left -= data_len;
+                       if (bytes_left == 0) {
+                               packet_type = LAST_PACKET;
+                               header_read = 0;
+                       } else
+                               packet_type = INTER_PACKET;
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       buffer, data_len);
+               }
+       }
+quit_stream:
+       if (gspca_dev->present) {
+               mutex_lock(&gspca_dev->usb_lock);
+               jl2005c_stop(gspca_dev);
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+       kfree(buffer);
+}
+
+
+
+
+/* This function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       cam = &gspca_dev->cam;
+       /* We don't use the buffer gspca allocates so make it small. */
+       cam->bulk_size = 64;
+       cam->bulk = 1;
+       /* For the rest, the camera needs to be detected */
+       jl2005c_get_firmware_id(gspca_dev);
+       /* Here are some known firmware IDs
+        * First some JL2005B cameras
+        * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam
+        * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B
+        * JL2005C cameras
+        * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512
+        * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly
+        * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz
+        *
+        * Based upon this scanty evidence, we can detect a CIF camera by
+        * testing byte 0 for 0x4x.
+        */
+       if ((sd->firmware_id[0] & 0xf0) == 0x40) {
+               cam->cam_mode   = cif_mode;
+               cam->nmodes     = ARRAY_SIZE(cif_mode);
+               sd->block_size  = 0x80;
+       } else {
+               cam->cam_mode   = vga_mode;
+               cam->nmodes     = ARRAY_SIZE(vga_mode);
+               sd->block_size  = 0x200;
+       }
+
+       INIT_WORK(&sd->work_struct, jl2005c_dostream);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+
+       struct sd *sd = (struct sd *) gspca_dev;
+       sd->cap_mode = gspca_dev->cam.cam_mode;
+
+       switch (gspca_dev->width) {
+       case 640:
+               PDEBUG(D_STREAM, "Start streaming at vga resolution");
+               jl2005c_stream_start_vga_lg(gspca_dev);
+               break;
+       case 320:
+               PDEBUG(D_STREAM, "Start streaming at qvga resolution");
+               jl2005c_stream_start_vga_small(gspca_dev);
+               break;
+       case 352:
+               PDEBUG(D_STREAM, "Start streaming at cif resolution");
+               jl2005c_stream_start_cif_lg(gspca_dev);
+               break;
+       case 176:
+               PDEBUG(D_STREAM, "Start streaming at qcif resolution");
+               jl2005c_stream_start_cif_small(gspca_dev);
+               break;
+       default:
+               pr_err("Unknown resolution specified\n");
+               return -1;
+       }
+
+       /* Start the workqueue function to do the streaming */
+       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(sd->work_thread, &sd->work_struct);
+
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       /* This waits for sq905c_dostream to finish */
+       destroy_workqueue(dev->work_thread);
+       dev->work_thread = NULL;
+       mutex_lock(&gspca_dev->usb_lock);
+}
+
+
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       /* .ctrls = none have been detected */
+       /* .nctrls = ARRAY_SIZE(sd_ctrls),  */
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stop0 = sd_stop0,
+};
+
+/* -- module initialisation -- */
+static const __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0979, 0x0227)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                               const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+                               THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+       int ret;
+
+       ret = usb_register(&sd_driver);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+       usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
index b1da7f4096c8b31dfb469d9b4bdd513beea7fadc..f0c0d74dfe928b781aeb486b7ea1d19ed27d138f 100644 (file)
@@ -247,9 +247,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        gspca_dev->cam.cam_mode = vga_mode;
        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
        gspca_dev->cam.no_urb_create = 1;
-       /* The highest alt setting has an isoc packetsize of 0, so we
-          don't want to use it */
-       gspca_dev->nbalt--;
 
        sd->brightness  = BRIGHTNESS_DEFAULT;
        sd->contrast    = CONTRAST_DEFAULT;
index 5c2ea05c46b49783aee1b7647950eca3baf29ac3..b0231465afae8b058702a7f56a78f563f996df8b 100644 (file)
@@ -263,7 +263,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        cam->nmodes = ARRAY_SIZE(vga_mode);
        cam->ctrls = sd->ctrls;
        sd->quality = QUALITY_DEF;
-       gspca_dev->nbalt = 9;           /* use the altsetting 08 */
        return 0;
 }
 
index d4bec9321771a41c49925e64d4844412d3628365..7167cac7359c565730cfd22cb3075be6fc27812b 100644 (file)
@@ -1763,8 +1763,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        if ((unsigned) webcam >= NWEBCAMS)
                webcam = 0;
        sd->webcam = webcam;
-       gspca_dev->cam.reverse_alts = 1;
        gspca_dev->cam.ctrls = sd->ctrls;
+       gspca_dev->cam.needs_full_bandwidth = 1;
        sd->ag_cnt = -1;
 
        /*
index 08b8ce1dee184a99d388520d4dba27b2afa617c3..739e8a2a2d308ea31268de9f625617d3dce27b0b 100644 (file)
@@ -3348,7 +3348,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        case BRIDGE_W9968CF:
                cam->cam_mode = w9968cf_vga_mode;
                cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
-               cam->reverse_alts = 1;
                break;
        }
 
@@ -3684,8 +3683,8 @@ static void ov511_mode_init_regs(struct sd *sd)
        /* Check if we have enough bandwidth to disable compression */
        fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
        needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
-       /* 1400 is a conservative estimate of the max nr of isoc packets/sec */
-       if (needed > 1400 * packet_size) {
+       /* 1000 isoc packets/sec */
+       if (needed > 1000 * packet_size) {
                /* Enable Y and UV quantization and compression */
                reg_w(sd, R511_COMP_EN, 0x07);
                reg_w(sd, R511_COMP_LUT_EN, 0x03);
index f30060d5063325d8277f7889d8bbb3f9f9716b30..fbfa02affa132908d02feceebac5b06ab44c9292 100644 (file)
@@ -71,6 +71,7 @@ struct sd {
 enum sensors {
        SENSOR_OV965x,          /* ov9657 */
        SENSOR_OV971x,          /* ov9712 */
+       SENSOR_OV562x,          /* ov5621 */
        NSENSORS
 };
 
@@ -207,6 +208,14 @@ static const struct v4l2_pix_format ov971x_mode[] = {
        }
 };
 
+static const struct v4l2_pix_format ov562x_mode[] = {
+       {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 2592,
+               .sizeimage = 2592 * 1680,
+               .colorspace = V4L2_COLORSPACE_SRGB
+       }
+};
+
 static const u8 bridge_init[][2] = {
        {0x88, 0xf8},
        {0x89, 0xff},
@@ -830,6 +839,124 @@ static const u8 ov965x_start_2_sxga[][2] = {
        {0xa3, 0x41},   /* bd60 */
 };
 
+static const u8 ov562x_init[][2] = {
+       {0x88, 0x20},
+       {0x89, 0x0a},
+       {0x8a, 0x90},
+       {0x8b, 0x06},
+       {0x8c, 0x01},
+       {0x8d, 0x10},
+       {0x1c, 0x00},
+       {0x1d, 0x48},
+       {0x1d, 0x00},
+       {0x1d, 0xff},
+       {0x1c, 0x0a},
+       {0x1d, 0x2e},
+       {0x1d, 0x1e},
+};
+
+static const u8 ov562x_init_2[][2] = {
+       {0x12, 0x80},
+       {0x11, 0x41},
+       {0x13, 0x00},
+       {0x10, 0x1e},
+       {0x3b, 0x07},
+       {0x5b, 0x40},
+       {0x39, 0x07},
+       {0x53, 0x02},
+       {0x54, 0x60},
+       {0x04, 0x20},
+       {0x27, 0x04},
+       {0x3d, 0x40},
+       {0x36, 0x00},
+       {0xc5, 0x04},
+       {0x4e, 0x00},
+       {0x4f, 0x93},
+       {0x50, 0x7b},
+       {0xca, 0x0c},
+       {0xcb, 0x0f},
+       {0x39, 0x07},
+       {0x4a, 0x10},
+       {0x3e, 0x0a},
+       {0x3d, 0x00},
+       {0x0c, 0x38},
+       {0x38, 0x90},
+       {0x46, 0x30},
+       {0x4f, 0x93},
+       {0x50, 0x7b},
+       {0xab, 0x00},
+       {0xca, 0x0c},
+       {0xcb, 0x0f},
+       {0x37, 0x02},
+       {0x44, 0x48},
+       {0x8d, 0x44},
+       {0x2a, 0x00},
+       {0x2b, 0x00},
+       {0x32, 0x00},
+       {0x38, 0x90},
+       {0x53, 0x02},
+       {0x54, 0x60},
+       {0x12, 0x00},
+       {0x17, 0x12},
+       {0x18, 0xb4},
+       {0x19, 0x0c},
+       {0x1a, 0xf4},
+       {0x03, 0x4a},
+       {0x89, 0x20},
+       {0x83, 0x80},
+       {0xb7, 0x9d},
+       {0xb6, 0x11},
+       {0xb5, 0x55},
+       {0xb4, 0x00},
+       {0xa9, 0xf0},
+       {0xa8, 0x0a},
+       {0xb8, 0xf0},
+       {0xb9, 0xf0},
+       {0xba, 0xf0},
+       {0x81, 0x07},
+       {0x63, 0x44},
+       {0x13, 0xc7},
+       {0x14, 0x60},
+       {0x33, 0x75},
+       {0x2c, 0x00},
+       {0x09, 0x00},
+       {0x35, 0x30},
+       {0x27, 0x04},
+       {0x3c, 0x07},
+       {0x3a, 0x0a},
+       {0x3b, 0x07},
+       {0x01, 0x40},
+       {0x02, 0x40},
+       {0x16, 0x40},
+       {0x52, 0xb0},
+       {0x51, 0x83},
+       {0x21, 0xbb},
+       {0x22, 0x10},
+       {0x23, 0x03},
+       {0x35, 0x38},
+       {0x20, 0x90},
+       {0x28, 0x30},
+       {0x73, 0xe1},
+       {0x6c, 0x00},
+       {0x6d, 0x80},
+       {0x6e, 0x00},
+       {0x70, 0x04},
+       {0x71, 0x00},
+       {0x8d, 0x04},
+       {0x64, 0x00},
+       {0x65, 0x00},
+       {0x66, 0x00},
+       {0x67, 0x00},
+       {0x68, 0x00},
+       {0x69, 0x00},
+       {0x6a, 0x00},
+       {0x6b, 0x00},
+       {0x71, 0x94},
+       {0x74, 0x20},
+       {0x80, 0x09},
+       {0x85, 0xc0},
+};
+
 static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
 {
        struct usb_device *udev = gspca_dev->dev;
@@ -1210,6 +1337,17 @@ static int sd_init(struct gspca_dev *gspca_dev)
                        reg_w(gspca_dev, 0x56, 0x1f);
                else
                        reg_w(gspca_dev, 0x56, 0x17);
+       } else if ((sensor_id & 0xfff0) == 0x5620) {
+               sd->sensor = SENSOR_OV562x;
+
+               gspca_dev->cam.cam_mode = ov562x_mode;
+               gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
+
+               reg_w_array(gspca_dev, ov562x_init,
+                               ARRAY_SIZE(ov562x_init));
+               sccb_w_array(gspca_dev, ov562x_init_2,
+                               ARRAY_SIZE(ov562x_init_2));
+               reg_w(gspca_dev, 0xe0, 0x00);
        } else {
                err("Unknown sensor %04x", sensor_id);
                return -EINVAL;
@@ -1222,7 +1360,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       if (sd->sensor == SENSOR_OV971x)
+       if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x)
                return gspca_dev->usb_err;
        switch (gspca_dev->curr_mode) {
        case QVGA_MODE:                 /* 320x240 */
@@ -1409,6 +1547,7 @@ static const struct sd_desc sd_desc = {
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x05a9, 0x8065)},
        {USB_DEVICE(0x06f8, 0x3003)},
+       {USB_DEVICE(0x05a9, 0x1550)},
        {}
 };
 
index ece8b1e82a13c6f4c8a876cddc3360d92690a27d..3844c49f269c4f06d1059ef65948ebfbdbdb1dc4 100644 (file)
@@ -41,14 +41,14 @@ MODULE_LICENSE("GPL");
 #define PAC207_BRIGHTNESS_DEFAULT      46
 
 #define PAC207_EXPOSURE_MIN            3
-#define PAC207_EXPOSURE_MAX            26
+#define PAC207_EXPOSURE_MAX            90 /* 1 sec expo time / 1 fps */
 #define PAC207_EXPOSURE_DEFAULT                5 /* power on default: 3 */
-#define PAC207_EXPOSURE_KNEE           8 /* 4 = 30 fps, 11 = 8, 15 = 6 */
+#define PAC207_EXPOSURE_KNEE           9 /* fps: 90 / exposure -> 9: 10 fps */
 
 #define PAC207_GAIN_MIN                        0
 #define PAC207_GAIN_MAX                        31
-#define PAC207_GAIN_DEFAULT            9 /* power on default: 9 */
-#define PAC207_GAIN_KNEE               31
+#define PAC207_GAIN_DEFAULT            7 /* power on default: 9 */
+#define PAC207_GAIN_KNEE               15
 
 #define PAC207_AUTOGAIN_DEADZONE       30
 
@@ -332,7 +332,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
        if (sd->autogain_ignore_frames > 0)
                sd->autogain_ignore_frames--;
        else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
-                       100, PAC207_AUTOGAIN_DEADZONE,
+                       90, PAC207_AUTOGAIN_DEADZONE,
                        PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
                sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 }
index 2811195258c48f816df23f370c8d264f2b6d232a..9db2b34d172cd9a6cab23bbb37847c3018ac3a90 100644 (file)
@@ -1197,6 +1197,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
        {USB_DEVICE(0x093a, 0x262a)},
        {USB_DEVICE(0x093a, 0x262c)},
+       {USB_DEVICE(0x145f, 0x013c)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
index 1494e1829d368a080eb9e6d5ec6fa3ec9606e983..bb70092c2229f3eca85d3795058595a4f981fd9e 100644 (file)
@@ -376,7 +376,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        cam->bulk_size = BULK_SIZE;
        cam->bulk_nurbs = 4;
        cam->ctrls = sd->ctrls;
-       gspca_dev->nbalt = 1;  /* Ignore the bogus isoc alt settings */
        sd->resetlevel = 0x2d; /* Set initial resetlevel */
 
        /* See if the camera supports brightness */
@@ -395,6 +394,14 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->alt = 1;     /* Ignore the bogus isoc alt settings */
+
+       return gspca_dev->usb_err;
+}
+
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
@@ -714,6 +721,7 @@ static const struct sd_desc sd_desc = {
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
        .init = sd_init,
+       .isoc_init = sd_isoc_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .dq_callback = sd_dq_callback,
index 33cabc342dcfcdf5ce24fa284e38f097eb18f119..9e198b45c3c804e11471ccff215c69471fa825ed 100644 (file)
@@ -2048,6 +2048,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
+       cam->needs_full_bandwidth = 1;
 
        sd->sensor = (id->driver_info >> 8) & 0xff;
        sd->i2c_addr = id->driver_info & 0xff;
@@ -2233,6 +2234,42 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
        }
 }
 
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_interface *intf;
+       u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
+
+       /*
+        * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
+        * than our regular bandwidth calculations reserve, so we force the
+        * use of a specific altsetting when using the SN9C20X_I420 fmt.
+        */
+       if (!(flags & (MODE_RAW | MODE_JPEG))) {
+               intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+
+               if (intf->num_altsetting != 9) {
+                       pr_warn("sn9c20x camera with unknown number of alt "
+                               "settings (%d), please report!\n",
+                               intf->num_altsetting);
+                       gspca_dev->alt = intf->num_altsetting;
+                       return 0;
+               }
+
+               switch (gspca_dev->width) {
+               case 160: /* 160x120 */
+                       gspca_dev->alt = 2;
+                       break;
+               case 320: /* 320x240 */
+                       gspca_dev->alt = 6;
+                       break;
+               default:  /* >= 640x480 */
+                       gspca_dev->alt = 9;
+               }
+       }
+
+       return 0;
+}
+
 #define HW_WIN(mode, hstart, vstart) \
 ((const u8 []){hstart, 0, vstart, 0, \
 (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
@@ -2473,6 +2510,7 @@ static const struct sd_desc sd_desc = {
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
        .init = sd_init,
+       .isoc_init = sd_isoc_init,
        .start = sd_start,
        .stopN = sd_stopN,
        .pkt_scan = sd_pkt_scan,
index ddb392dc4f2dbd7b52efd0fffb52311b7e4f42f3..6a1148d7fe926772a245482ba16dca48947467f8 100644 (file)
@@ -1079,20 +1079,23 @@ static int sd_config(struct gspca_dev *gspca_dev,
        }
        cam->npkt = 36;                 /* 36 packets per ISOC message */
 
-       if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
-               sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
-               sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
-               sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
-       }
-
        return 0;
 }
 
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
        const __u8 stop = 0x09; /* Disable stream turn of LED */
 
+       if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
+               sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
+               sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
+               sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
+               if (sd->ctrls[EXPOSURE].val > COARSE_EXPOSURE_MAX)
+                       sd->ctrls[EXPOSURE].val = COARSE_EXPOSURE_DEF;
+       }
+
        reg_w(gspca_dev, 0x01, &stop, 1);
 
        return 0;
index afa3186b803860a5b36e03e7187b5271d56d5d6c..0c9e6ddabd2cc9a43d94dcbc5c1591b280031244 100644 (file)
@@ -1235,7 +1235,7 @@ static const u8 po2030n_sensor_param1[][8] = {
        {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
        {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
        {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10},
+       {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
 /*param2*/
        {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
        {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
@@ -1779,10 +1779,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->ag_cnt = -1;
        sd->quality = QUALITY_DEF;
 
-       /* if USB 1.1, let some bandwidth for the audio device */
-       if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
-               gspca_dev->nbalt--;
-
        INIT_WORK(&sd->work, qual_upd);
 
        return 0;
@@ -2063,6 +2059,16 @@ static void setredblue(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
+       if (sd->sensor == SENSOR_PO2030N) {
+               u8 rg1b[] =             /* red  green1 blue (no g2) */
+                       {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
+
+               /* 0x40 = normal value = gain x 1 */
+               rg1b[3] = sd->ctrls[RED].val * 2;
+               rg1b[5] = sd->ctrls[BLUE].val * 2;
+               i2c_w8(gspca_dev, rg1b);
+               return;
+       }
        reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
 /*     reg_w1(gspca_dev, 0x07, 32); */
        reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
@@ -2397,7 +2403,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0x17, reg17);
        reg01 &= ~S_PWR_DN;             /* sensor power on */
        reg_w1(gspca_dev, 0x01, reg01);
-       reg01 &= ~SYS_SEL_48M;
+       reg01 &= ~SCL_SEL_OD;           /* remove open-drain mode */
        reg_w1(gspca_dev, 0x01, reg01);
 
        switch (sd->sensor) {
index 259a0c73c664b9c02966ba3253d41981b8eeae83..4a5f209ce719aa878ae082d30ca82f9faa9586f3 100644 (file)
@@ -451,7 +451,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        }
 
        cam = &gspca_dev->cam;
-       gspca_dev->nbalt = 7 + 1;       /* choose alternate 7 first */
+       cam->needs_full_bandwidth = 1;
 
        sd->chip_revision = id->driver_info;
        if (sd->chip_revision == Rev012A) {
index 6f878f6c6e996283427d62ffd5ffee4d1a4b7dd7..91d99b4cc57bf69afca371e70e0b5527abd1625d 100644 (file)
@@ -304,7 +304,7 @@ static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-       alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
        alt->endpoint[0].desc.wMaxPacketSize =
                cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
 
@@ -317,7 +317,7 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
        struct usb_host_interface *alt;
        struct sd *sd = (struct sd *) gspca_dev;
 
-       alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
        packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
        min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
        if (packet_size <= min_packet_size)
index ea44deb66af4bbf9b9f7f871f70394804afd621d..9b9f85a8e60e750f9d2fba5cb4a0deab8e4f3b63 100644 (file)
@@ -30,6 +30,7 @@
 
 #define MODULE_NAME "t613"
 
+#include <linux/input.h>
 #include <linux/slab.h>
 #include "gspca.h"
 
@@ -57,6 +58,7 @@ struct sd {
        u8 effect;
 
        u8 sensor;
+       u8 button_pressed;
 };
 enum sensors {
        SENSOR_OM6802,
@@ -1095,15 +1097,35 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                msleep(20);
                reg_w(gspca_dev, 0x0309);
        }
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->button_pressed) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->button_pressed = 0;
+       }
+#endif
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,                       /* isoc packet */
                        int len)                        /* iso packet length */
 {
+       struct sd *sd = (struct sd *) gspca_dev;
        int pkt_type;
 
        if (data[0] == 0x5a) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+               if (len > 20) {
+                       u8 state = (data[20] & 0x80) ? 1 : 0;
+                       if (sd->button_pressed != state) {
+                               input_report_key(gspca_dev->input_dev,
+                                                KEY_CAMERA, state);
+                               input_sync(gspca_dev->input_dev);
+                               sd->button_pressed = state;
+                       }
+               }
+#endif
                /* Control Packet, after this came the header again,
                 * but extra bytes came in the packet before this,
                 * sometimes an EOF arrives, sometimes not... */
@@ -1410,6 +1432,9 @@ static const struct sd_desc sd_desc = {
        .stopN = sd_stopN,
        .pkt_scan = sd_pkt_scan,
        .querymenu = sd_querymenu,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
 };
 
 /* -- module initialisation -- */
index b2695b1dc6032a28312d411aa244db1979882759..444d3c5b90795db1c4c127d696c2a08fef7dd5fb 100644 (file)
@@ -3946,7 +3946,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
                /* 640x480 * 30 fps does not work */
                if (i == 6                      /* if 30 fps */
                 && gspca_dev->width == 640)
-                       i = 0x86;               /* 15 fps */
+                       i = 0x05;               /* 15 fps */
        } else {
                for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
                        if (sd->framerate >= rates_6810[i])
index d12ea1518ace7df6351ccda64de3b3d7a7cd8994..911152e169d6d43c4a42dd47fffa0542dd1e96f9 100644 (file)
@@ -324,7 +324,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        dev->work_thread = NULL;
        mutex_lock(&gspca_dev->usb_lock);
 
-       vicam_set_camera_power(gspca_dev, 0);
+       if (gspca_dev->present)
+               vicam_set_camera_power(gspca_dev, 0);
 }
 
 /* Table of supported USB devices */
index fbb6ed25ec313a007086f933a0f6bb7efcbc697a..ecada178bceb9b27bc0c3d6d0a2d505100ccb3b4 100644 (file)
@@ -995,14 +995,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
        case CIT_MODEL0:
                cam->cam_mode = model0_mode;
                cam->nmodes = ARRAY_SIZE(model0_mode);
-               cam->reverse_alts = 1;
                gspca_dev->ctrl_dis = ~((1 << SD_CONTRAST) | (1 << SD_HFLIP));
                sd->sof_len = 4;
                break;
        case CIT_MODEL1:
                cam->cam_mode = cif_yuv_mode;
                cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
-               cam->reverse_alts = 1;
                gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_HFLIP);
                sd->sof_len = 4;
                break;
@@ -2791,7 +2789,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
        }
 
        /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-       alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
        alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
 
        return 0;
@@ -2814,7 +2812,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
                break;
        }
 
-       alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
        packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
        if (packet_size <= min_packet_size)
                return -EIO;
index 0202fead6b9746e4330b6666db2ee09cea545ea0..b9e15bb0328bef03dab33169c3d14fbebee44cbc 100644 (file)
@@ -5381,12 +5381,12 @@ static const struct usb_action tas5130c_NoFlikerScale[] = {
        {}
 };
 
-static const struct usb_action gc0303_InitialScale[] = {
+/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */
+static const struct usb_action gc0303_Initial[] = {
        {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
        {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
        {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},           /* 00,02,00,cc,
-                                                        * 0<->10 */
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
        {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
        {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
        {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
@@ -5405,29 +5405,22 @@ static const struct usb_action gc0303_InitialScale[] = {
                                                         * 6<->8 */
        {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
        {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xaa, 0x1b, 0x0024},           /* 00,1b,24,aa, */
-       {0xdd, 0x00, 0x0080},           /* 00,00,80,dd, */
-       {0xaa, 0x1b, 0x0000},           /* 00,1b,00,aa, */
-       {0xaa, 0x13, 0x0002},           /* 00,13,02,aa, */
-       {0xaa, 0x15, 0x0004},           /* 00,15,04,aa */
-/*??   {0xaa, 0x01, 0x0000}, */
        {0xaa, 0x01, 0x0000},
        {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
        {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
+       {0xaa, 0x1b, 0x0000},
        {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},           /* 00,86,82,cc, */
        {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},            /* 00,87,83,cc, */
        {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},            /* 00,88,84,cc, */
        {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
-       {0xaa, 0x0a, 0x0000},           /* 00,0a,00,aa, */
-       {0xaa, 0x0b, 0x00a0},           /* 00,0b,a0,aa, */
-       {0xaa, 0x0c, 0x0000},           /* 00,0c,00,aa, */
-       {0xaa, 0x0d, 0x00a0},           /* 00,0d,a0,aa, */
-       {0xaa, 0x0e, 0x0000},           /* 00,0e,00,aa, */
-       {0xaa, 0x0f, 0x00a0},           /* 00,0f,a0,aa, */
-       {0xaa, 0x10, 0x0000},           /* 00,10,00,aa, */
-       {0xaa, 0x11, 0x00a0},           /* 00,11,a0,aa, */
-/*??   {0xa0, 0x00, 0x0039},
-       {0xa1, 0x01, 0x0037}, */
+       {0xaa, 0x0a, 0x0002},
+       {0xaa, 0x0b, 0x0000},
+       {0xaa, 0x0c, 0x0002},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0002},
+       {0xaa, 0x0f, 0x0000},
+       {0xaa, 0x10, 0x0002},
+       {0xaa, 0x11, 0x0000},
        {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
        {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa, (e6 -> e8) */
        {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
@@ -5442,17 +5435,18 @@ static const struct usb_action gc0303_InitialScale[] = {
        {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
        {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
        {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},           /* 01,a8,60,cc, */
+       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
        {0xa0, 0x61, ZC3XX_R116_RGAIN},                 /* 01,16,61,cc, */
        {0xa0, 0x65, ZC3XX_R118_BGAIN},                 /* 01,18,65,cc */
+       {0xaa, 0x1b, 0x0000},
        {}
 };
 
-static const struct usb_action gc0303_Initial[] = {
+static const struct usb_action gc0303_InitialScale[] = {
        {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
        {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
        {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},           /* 00,02,10,cc, */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
        {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
        {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
        {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
@@ -5471,34 +5465,26 @@ static const struct usb_action gc0303_Initial[] = {
                                                         * 8<->6 */
        {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
        {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xaa, 0x1b, 0x0024},           /* 00,1b,24,aa, */
-       {0xdd, 0x00, 0x0080},           /* 00,00,80,dd, */
-       {0xaa, 0x1b, 0x0000},           /* 00,1b,00,aa, */
-       {0xaa, 0x13, 0x0002},           /* 00,13,02,aa, */
-       {0xaa, 0x15, 0x0004},           /* 00,15,04,aa */
-/*??   {0xaa, 0x01, 0x0000}, */
        {0xaa, 0x01, 0x0000},
        {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
        {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
+       {0xaa, 0x1b, 0x0000},
        {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc, */
        {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc, */
        {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc, */
        {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
-       {0xaa, 0x0a, 0x0000},           /* 00,0a,00,aa, */
-       {0xaa, 0x0b, 0x00a0},           /* 00,0b,a0,aa, */
-       {0xaa, 0x0c, 0x0000},           /* 00,0c,00,aa, */
-       {0xaa, 0x0d, 0x00a0},           /* 00,0d,a0,aa, */
-       {0xaa, 0x0e, 0x0000},           /* 00,0e,00,aa, */
-       {0xaa, 0x0f, 0x00a0},           /* 00,0f,a0,aa, */
-       {0xaa, 0x10, 0x0000},           /* 00,10,00,aa, */
-       {0xaa, 0x11, 0x00a0},           /* 00,11,a0,aa, */
-/*??   {0xa0, 0x00, 0x0039},
-       {0xa1, 0x01, 0x0037}, */
+       {0xaa, 0x0a, 0x0001},
+       {0xaa, 0x0b, 0x0000},
+       {0xaa, 0x0c, 0x0001},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0001},
+       {0xaa, 0x0f, 0x0000},
+       {0xaa, 0x10, 0x0001},
+       {0xaa, 0x11, 0x0000},
        {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
        {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa (e6 -> e8) */
        {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
        {0xaa, 0x19, 0x0088},           /* 00,19,88,aa, */
-       {0xaa, 0x20, 0x0020},           /* 00,20,20,aa, */
        {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc, */
        {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc, */
        {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc, */
@@ -5508,36 +5494,37 @@ static const struct usb_action gc0303_Initial[] = {
        {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
        {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
        {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},           /* 01,a8,60,cc, */
+       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
        {0xa0, 0x61, ZC3XX_R116_RGAIN},         /* 01,16,61,cc, */
        {0xa0, 0x65, ZC3XX_R118_BGAIN},         /* 01,18,65,cc */
+       {0xaa, 0x1b, 0x0000},
        {}
 };
-static const struct usb_action gc0303_50HZScale[] = {
+static const struct usb_action gc0303_50HZ[] = {
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
        {0xaa, 0x83, 0x0001},           /* 00,83,01,aa */
-       {0xaa, 0x84, 0x00aa},           /* 00,84,aa,aa */
+       {0xaa, 0x84, 0x0063},
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
        {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0d,cc, */
        {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,50,cc, */
        {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
        {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,47,cc, */
+       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,47,cc, */
        {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
        {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
        {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
+       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},
        {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
        {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
        {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
        {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
        {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
        {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},               /* 01,8d,78,cc */
+       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
        {}
 };
 
-static const struct usb_action gc0303_50HZ[] = {
+static const struct usb_action gc0303_50HZScale[] = {
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
        {0xaa, 0x83, 0x0003},           /* 00,83,03,aa */
        {0xaa, 0x84, 0x0054},           /* 00,84,54,aa */
@@ -5550,21 +5537,21 @@ static const struct usb_action gc0303_50HZ[] = {
        {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
        {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
        {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
+       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
        {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
        {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
        {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
        {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
        {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
        {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},               /* 01,8d,78,cc */
+       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
        {}
 };
 
-static const struct usb_action gc0303_60HZScale[] = {
+static const struct usb_action gc0303_60HZ[] = {
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0001},           /* 00,83,01,aa */
-       {0xaa, 0x84, 0x0062},           /* 00,84,62,aa */
+       {0xaa, 0x83, 0x0000},
+       {0xaa, 0x84, 0x003b},
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
        {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,05,cc, */
        {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,88,cc, */
@@ -5581,14 +5568,14 @@ static const struct usb_action gc0303_60HZScale[] = {
        {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
        {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
        {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},               /* 01,8d,78,cc */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
        {}
 };
 
-static const struct usb_action gc0303_60HZ[] = {
+static const struct usb_action gc0303_60HZScale[] = {
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0002},           /* 00,83,02,aa */
-       {0xaa, 0x84, 0x00c4},           /* 00,84,c4,aa */
+       {0xaa, 0x83, 0x0000},
+       {0xaa, 0x84, 0x0076},
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
        {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,1,0b,cc, */
        {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,2,10,cc, */
@@ -5605,18 +5592,18 @@ static const struct usb_action gc0303_60HZ[] = {
        {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,0,ff,cc, */
        {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,d,58,cc, */
        {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},               /* 01,d,78,cc */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
        {}
 };
 
-static const struct usb_action gc0303_NoFlikerScale[] = {
+static const struct usb_action gc0303_NoFliker[] = {
        {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
        {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
        {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,0,00,cc, */
-       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,05,cc, */
-       {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,88,cc, */
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
        {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
        {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
        {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
@@ -5631,14 +5618,14 @@ static const struct usb_action gc0303_NoFlikerScale[] = {
        {}
 };
 
-static const struct usb_action gc0303_NoFliker[] = {
+static const struct usb_action gc0303_NoFlikerScale[] = {
        {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
        {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
        {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
        {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
        {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0b,cc, */
-       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,10,cc, */
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
        {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
        {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
        {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
@@ -5809,7 +5796,7 @@ static void setmatrix(struct gspca_dev *gspca_dev)
        static const u8 tas5130c_matrix[9] =
                {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
        static const u8 gc0303_matrix[9] =
-               {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
+               {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c};
        static const u8 *matrix_tb[SENSOR_MAX] = {
                [SENSOR_ADCM2700] =     adcm2700_matrix,
                [SENSOR_CS2102] =       ov7620_matrix,
@@ -6426,10 +6413,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        gspca_dev->cam.ctrls = sd->ctrls;
        sd->quality = QUALITY_DEF;
 
-       /* if USB 1.1, let some bandwidth for the audio device */
-       if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
-               gspca_dev->nbalt--;
-
        return 0;
 }
 
index 3ab875d036e10cdc1a530cffb75246a76bdc3d2f..a7c41d32f4140b02e03350d2e4222b2a0fd38430 100644 (file)
@@ -244,7 +244,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
 /* ----------------------------------------------------------------------- */
 
-static void ir_key_poll(struct IR_i2c *ir)
+static int ir_key_poll(struct IR_i2c *ir)
 {
        static u32 ir_key, ir_raw;
        int rc;
@@ -253,20 +253,28 @@ static void ir_key_poll(struct IR_i2c *ir)
        rc = ir->get_key(ir, &ir_key, &ir_raw);
        if (rc < 0) {
                dprintk(2,"error\n");
-               return;
+               return rc;
        }
 
        if (rc) {
                dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
                rc_keydown(ir->rc, ir_key, 0);
        }
+       return 0;
 }
 
 static void ir_work(struct work_struct *work)
 {
+       int rc;
        struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
 
-       ir_key_poll(ir);
+       rc = ir_key_poll(ir);
+       if (rc == -ENODEV) {
+               rc_unregister_device(ir->rc);
+               ir->rc = NULL;
+               return;
+       }
+
        schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
 }
 
@@ -446,7 +454,8 @@ static int ir_remove(struct i2c_client *client)
        cancel_delayed_work_sync(&ir->work);
 
        /* unregister device */
-       rc_unregister_device(ir->rc);
+       if (ir->rc)
+               rc_unregister_device(ir->rc);
 
        /* free memory */
        kfree(ir);
@@ -489,11 +498,3 @@ static void __exit ir_fini(void)
 
 module_init(ir_init);
 module_exit(ir_fini);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 9332920ca4ff9ff672fa486473a7a7042049f0bf..7b9ec1cfeb80f69bb16a6a476e7b125c44e71bc7 100644 (file)
@@ -25,7 +25,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv);
 int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
 struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
 int init_ivtv_i2c(struct ivtv *itv);
 void exit_ivtv_i2c(struct ivtv *itv);
 
index 82c8817bd32dcddcc74a98593919bd64502de237..4b021e1ee5f26f7e6a3407fcebdc2b74bf706786 100644 (file)
@@ -163,7 +163,6 @@ struct m5mols_version {
  * @ffmt: current fmt according to resolution type
  * @res_type: current resolution type
  * @irq_waitq: waitqueue for the capture
- * @work_irq: workqueue for the IRQ
  * @flags: state variable for the interrupt handler
  * @handle: control handler
  * @autoexposure: Auto Exposure control
@@ -175,14 +174,12 @@ struct m5mols_version {
  * @ver: information of the version
  * @cap: the capture mode attributes
  * @power: current sensor's power status
- * @ctrl_sync: true means all controls of the sensor are initialized
- * @int_capture: true means the capture interrupt is issued once
+ * @isp_ready: 1 when the ISP controller has completed booting
+ * @ctrl_sync: 1 when the control handler state is restored in H/W
  * @lock_ae: true means the Auto Exposure is locked
  * @lock_awb: true means the Aut WhiteBalance is locked
  * @resolution:        register value for current resolution
- * @interrupt: register value for current interrupt status
  * @mode: register value for current operation mode
- * @mode_save: register value for current operation mode for saving
  * @set_power: optional power callback to the board code
  */
 struct m5mols_info {
@@ -191,16 +188,16 @@ struct m5mols_info {
        struct media_pad pad;
        struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
        int res_type;
+
        wait_queue_head_t irq_waitq;
-       struct work_struct work_irq;
-       unsigned long flags;
+       atomic_t irq_done;
 
        struct v4l2_ctrl_handler handle;
+
        /* Autoexposure/exposure control cluster */
-       struct {
-               struct v4l2_ctrl *autoexposure;
-               struct v4l2_ctrl *exposure;
-       };
+       struct v4l2_ctrl *autoexposure;
+       struct v4l2_ctrl *exposure;
+
        struct v4l2_ctrl *autowb;
        struct v4l2_ctrl *colorfx;
        struct v4l2_ctrl *saturation;
@@ -208,21 +205,19 @@ struct m5mols_info {
 
        struct m5mols_version ver;
        struct m5mols_capture cap;
-       bool power;
-       bool ctrl_sync;
+
+       unsigned int isp_ready:1;
+       unsigned int power:1;
+       unsigned int ctrl_sync:1;
+
        bool lock_ae;
        bool lock_awb;
        u8 resolution;
-       u8 interrupt;
        u8 mode;
-       u8 mode_save;
+
        int (*set_power)(struct device *dev, int on);
 };
 
-#define ST_CAPT_IRQ 0
-
-#define is_powered(__info) (__info->power)
-#define is_ctrl_synced(__info) (__info->ctrl_sync)
 #define is_available_af(__info)        (__info->ver.af)
 #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
 #define is_manufacturer(__info, __manufacturer)        \
@@ -257,7 +252,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
 int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
 int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
 int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
+
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+                    int timeout);
+
+/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
+#define M5MOLS_I2C_RDY_WAIT_FL         (1 << 16)
+/* ISP state transition timeout, in ms */
+#define M5MOLS_MODE_CHANGE_TIMEOUT     200
+#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT   250
 
 /*
  * Mode operation of the M-5MOLS
@@ -282,7 +285,8 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
 int m5mols_mode(struct m5mols_info *info, u8 mode);
 
 int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
-int m5mols_sync_controls(struct m5mols_info *info);
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
+int m5mols_restore_controls(struct m5mols_info *info);
 int m5mols_start_capture(struct m5mols_info *info);
 int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
 int m5mols_lock_3a(struct m5mols_info *info, bool lock);
index 3248ac8057119dcabbe0c726206f9fa60e2ca612..ba25e8e2ba4c789ba391800e88602cfba6a3aecd 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * The Capture code for Fujitsu M-5MOLS ISP
  *
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 #include <media/m5mols.h>
+#include <media/s5p_fimc.h>
 
 #include "m5mols.h"
 #include "m5mols_reg.h"
 
-static int m5mols_capture_error_handler(struct m5mols_info *info,
-                                       int timeout)
-{
-       int ret;
-
-       /* Disable all interrupts and clear relevant interrupt staus bits */
-       ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,
-                          info->interrupt & ~(REG_INT_CAPTURE));
-       if (ret)
-               return ret;
-
-       if (timeout == 0)
-               return -ETIMEDOUT;
-
-       return 0;
-}
 /**
  * m5mols_read_rational - I2C read of a rational number
  *
@@ -121,69 +107,54 @@ int m5mols_start_capture(struct m5mols_info *info)
 {
        struct v4l2_subdev *sd = &info->sd;
        u8 resolution = info->resolution;
-       int timeout;
        int ret;
 
        /*
-        * Preparing capture. Setting control & interrupt before entering
-        * capture mode
-        *
-        * 1) change to MONITOR mode for operating control & interrupt
-        * 2) set controls (considering v4l2_control value & lock 3A)
-        * 3) set interrupt
-        * 4) change to CAPTURE mode
+        * Synchronize the controls, set the capture frame resolution and color
+        * format. The frame capture is initiated during switching from Monitor
+        * to Capture mode.
         */
        ret = m5mols_mode(info, REG_MONITOR);
        if (!ret)
-               ret = m5mols_sync_controls(info);
+               ret = m5mols_restore_controls(info);
        if (!ret)
-               ret = m5mols_lock_3a(info, true);
+               ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
+       if (!ret)
+               ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
        if (!ret)
-               ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
+               ret = m5mols_lock_3a(info, true);
        if (!ret)
                ret = m5mols_mode(info, REG_CAPTURE);
-       if (!ret) {
-               /* Wait for capture interrupt, after changing capture mode */
-               timeout = wait_event_interruptible_timeout(info->irq_waitq,
-                                          test_bit(ST_CAPT_IRQ, &info->flags),
-                                          msecs_to_jiffies(2000));
-               if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags))
-                       ret = m5mols_capture_error_handler(info, timeout);
-       }
+       if (!ret)
+               /* Wait until a frame is captured to ISP internal memory */
+               ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
        if (!ret)
                ret = m5mols_lock_3a(info, false);
        if (ret)
                return ret;
+
        /*
-        * Starting capture. Setting capture frame count and resolution and
-        * the format(available format: JPEG, Bayer RAW, YUV).
-        *
-        * 1) select single or multi(enable to 25), format, size
-        * 2) set interrupt
-        * 3) start capture(for main image, now)
-        * 4) get information
-        * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)
+        * Initiate the captured data transfer to a MIPI-CSI receiver.
         */
        ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
-       if (!ret)
-               ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
        if (!ret)
                ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
        if (!ret) {
+               bool captured = false;
+               unsigned int size;
+
                /* Wait for the capture completion interrupt */
-               timeout = wait_event_interruptible_timeout(info->irq_waitq,
-                                          test_bit(ST_CAPT_IRQ, &info->flags),
-                                          msecs_to_jiffies(2000));
-               if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) {
+               ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
+               if (!ret) {
+                       captured = true;
                        ret = m5mols_capture_info(info);
-                       if (!ret)
-                               v4l2_subdev_notify(sd, 0, &info->cap.total);
                }
+               size = captured ? info->cap.main : 0;
+               v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n",
+                        __func__, size, info->cap.thumb);
+
+               v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size);
        }
 
-       return m5mols_capture_error_handler(info, timeout);
+       return ret;
 }
index e0f09e531800d193c1cb0250cb89d820d7fa1236..93d768db9f3328b152bf8f1a98329fc475c11d2d 100644 (file)
@@ -135,10 +135,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
  * @reg: combination of size, category and command for the I2C packet
  * @size: desired size of I2C packet
  * @val: read value
+ *
+ * Returns 0 on success, or else negative errno.
  */
 static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct m5mols_info *info = to_m5mols(sd);
        u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
        u8 category = I2C_CATEGORY(reg);
        u8 cmd = I2C_COMMAND(reg);
@@ -168,15 +171,17 @@ static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
        usleep_range(200, 200);
 
        ret = i2c_transfer(client->adapter, msg, 2);
-       if (ret < 0) {
-               v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
-                        size, category, cmd, ret);
-               return ret;
+
+       if (ret == 2) {
+               *val = m5mols_swap_byte(&rbuf[1], size);
+               return 0;
        }
 
-       *val = m5mols_swap_byte(&rbuf[1], size);
+       if (info->isp_ready)
+               v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
+                        size, category, cmd, ret);
 
-       return 0;
+       return ret < 0 ? ret : -EIO;
 }
 
 int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
@@ -229,10 +234,13 @@ int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
  * m5mols_write - I2C command write function
  * @reg: combination of size, category and command for the I2C packet
  * @val: value to write
+ *
+ * Returns 0 on success, or else negative errno.
  */
 int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct m5mols_info *info = to_m5mols(sd);
        u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
        u8 category = I2C_CATEGORY(reg);
        u8 cmd = I2C_COMMAND(reg);
@@ -263,28 +271,45 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
        usleep_range(200, 200);
 
        ret = i2c_transfer(client->adapter, msg, 1);
-       if (ret < 0) {
-               v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n",
-                       size, category, cmd, ret);
-               return ret;
-       }
+       if (ret == 1)
+               return 0;
 
-       return 0;
+       if (info->isp_ready)
+               v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
+                        category, cmd, ret);
+
+       return ret < 0 ? ret : -EIO;
 }
 
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
+/**
+ * m5mols_busy_wait - Busy waiting with I2C register polling
+ * @reg: the I2C_REG() address of an 8-bit status register to check
+ * @value: expected status register value
+ * @mask: bit mask for the read status register value
+ * @timeout: timeout in miliseconds, or -1 for default timeout
+ *
+ * The @reg register value is ORed with @mask before comparing with @value.
+ *
+ * Return: 0 if the requested condition became true within less than
+ *         @timeout ms, or else negative errno.
+ */
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+                    int timeout)
 {
-       u8 busy;
-       int i;
-       int ret;
+       int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
+       unsigned long end = jiffies + msecs_to_jiffies(ms);
+       u8 status;
 
-       for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
-               ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
-               if (ret < 0)
+       do {
+               int ret = m5mols_read_u8(sd, reg, &status);
+
+               if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
                        return ret;
-               if ((busy & mask) == mask)
+               if (!ret && (status & mask & 0xff) == (value & 0xff))
                        return 0;
-       }
+               usleep_range(100, 250);
+       } while (ms > 0 && time_is_after_jiffies(end));
+
        return -EBUSY;
 }
 
@@ -307,6 +332,20 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
        return ret;
 }
 
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+
+       int ret = wait_event_interruptible_timeout(info->irq_waitq,
+                               atomic_add_unless(&info->irq_done, -1, 0),
+                               msecs_to_jiffies(timeout));
+       if (ret <= 0)
+               return ret ? ret : -ETIMEDOUT;
+
+       return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
+                               M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
+}
+
 /**
  * m5mols_reg_mode - Write the mode and check busy status
  *
@@ -316,8 +355,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
 static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
 {
        int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
-
-       return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode);
+       if (ret < 0)
+               return ret;
+       return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
+                               M5MOLS_MODE_CHANGE_TIMEOUT);
 }
 
 /**
@@ -338,13 +379,13 @@ int m5mols_mode(struct m5mols_info *info, u8 mode)
                return ret;
 
        ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
-       if ((!ret && reg == mode) || ret)
+       if (ret || reg == mode)
                return ret;
 
        switch (reg) {
        case REG_PARAMETER:
                ret = m5mols_reg_mode(sd, REG_MONITOR);
-               if (!ret && mode == REG_MONITOR)
+               if (mode == REG_MONITOR)
                        break;
                if (!ret)
                        ret = m5mols_reg_mode(sd, REG_CAPTURE);
@@ -361,7 +402,7 @@ int m5mols_mode(struct m5mols_info *info, u8 mode)
 
        case REG_CAPTURE:
                ret = m5mols_reg_mode(sd, REG_MONITOR);
-               if (!ret && mode == REG_MONITOR)
+               if (mode == REG_MONITOR)
                        break;
                if (!ret)
                        ret = m5mols_reg_mode(sd, REG_PARAMETER);
@@ -570,26 +611,25 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
 };
 
 /**
- * m5mols_sync_controls - Apply default scene mode and the current controls
+ * m5mols_restore_controls - Apply current control values to the registers
  *
- * This is used only streaming for syncing between v4l2_ctrl framework and
- * m5mols's controls. First, do the scenemode to the sensor, then call
- * v4l2_ctrl_handler_setup. It can be same between some commands and
- * the scenemode's in the default v4l2_ctrls. But, such commands of control
- * should be prior to the scenemode's one.
+ * m5mols_do_scenemode() handles all parameters for which there is yet no
+ * individual control. It should be replaced at some point by setting each
+ * control individually, in required register set up order.
  */
-int m5mols_sync_controls(struct m5mols_info *info)
+int m5mols_restore_controls(struct m5mols_info *info)
 {
-       int ret = -EINVAL;
+       int ret;
 
-       if (!is_ctrl_synced(info)) {
-               ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
-               if (ret)
-                       return ret;
+       if (info->ctrl_sync)
+               return 0;
 
-               v4l2_ctrl_handler_setup(&info->handle);
-               info->ctrl_sync = true;
-       }
+       ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
+       if (ret)
+               return ret;
+
+       ret = v4l2_ctrl_handler_setup(&info->handle);
+       info->ctrl_sync = !ret;
 
        return ret;
 }
@@ -613,7 +653,7 @@ static int m5mols_start_monitor(struct m5mols_info *info)
        if (!ret)
                ret = m5mols_mode(info, REG_MONITOR);
        if (!ret)
-               ret = m5mols_sync_controls(info);
+               ret = m5mols_restore_controls(info);
 
        return ret;
 }
@@ -645,17 +685,25 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct v4l2_subdev *sd = to_sd(ctrl);
        struct m5mols_info *info = to_m5mols(sd);
+       int ispstate = info->mode;
        int ret;
 
-       info->mode_save = info->mode;
+       /*
+        * If needed, defer restoring the controls until
+        * the device is fully initialized.
+        */
+       if (!info->isp_ready) {
+               info->ctrl_sync = 0;
+               return 0;
+       }
 
        ret = m5mols_mode(info, REG_PARAMETER);
-       if (!ret)
-               ret = m5mols_set_ctrl(ctrl);
-       if (!ret)
-               ret = m5mols_mode(info, info->mode_save);
-
-       return ret;
+       if (ret < 0)
+               return ret;
+       ret = m5mols_set_ctrl(ctrl);
+       if (ret < 0)
+               return ret;
+       return m5mols_mode(info, ispstate);
 }
 
 static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
@@ -669,10 +717,10 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
        const struct m5mols_platform_data *pdata = info->pdata;
        int ret;
 
-       if (enable) {
-               if (is_powered(info))
-                       return 0;
+       if (info->power == enable)
+               return 0;
 
+       if (enable) {
                if (info->set_power) {
                        ret = info->set_power(&client->dev, 1);
                        if (ret)
@@ -686,15 +734,11 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
                }
 
                gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
-               usleep_range(1000, 1000);
-               info->power = true;
+               info->power = 1;
 
                return ret;
        }
 
-       if (!is_powered(info))
-               return 0;
-
        ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
        if (ret)
                return ret;
@@ -703,8 +747,9 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
                info->set_power(&client->dev, 0);
 
        gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
-       usleep_range(1000, 1000);
-       info->power = false;
+
+       info->isp_ready = 0;
+       info->power = 0;
 
        return ret;
 }
@@ -717,21 +762,29 @@ int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
 }
 
 /**
- * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core.
+ * m5mols_fw_start - M-5MOLS internal ARM controller initialization
  *
- * Booting internal ARM core makes the M-5MOLS is ready for getting commands
- * with I2C. It's the first thing to be done after it powered up. It must wait
- * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting.
+ * Execute the M-5MOLS internal ARM controller initialization sequence.
+ * This function should be called after the supply voltage has been
+ * applied and before any requests to the device are made.
  */
-static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
+static int m5mols_fw_start(struct v4l2_subdev *sd)
 {
+       struct m5mols_info *info = to_m5mols(sd);
        int ret;
 
-       ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+       atomic_set(&info->irq_done, 0);
+       /* Wait until I2C slave is initialized in Flash Writer mode */
+       ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
+                              M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
+       if (!ret)
+               ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+       if (!ret)
+               ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
        if (ret < 0)
                return ret;
 
-       msleep(520);
+       info->isp_ready = 1;
 
        ret = m5mols_get_version(sd);
        if (!ret)
@@ -743,7 +796,8 @@ static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
 
        ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
        if (!ret)
-               ret = m5mols_enable_interrupt(sd, REG_INT_AF);
+               ret = m5mols_enable_interrupt(sd,
+                               REG_INT_AF | REG_INT_CAPTURE);
 
        return ret;
 }
@@ -780,7 +834,7 @@ static int m5mols_init_controls(struct m5mols_info *info)
                        4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE);
        info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle,
                        &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
-                       1, 0, V4L2_EXPOSURE_MANUAL);
+                       1, 0, V4L2_EXPOSURE_AUTO);
 
        sd->ctrl_handler = &info->handle;
        if (info->handle.error) {
@@ -809,16 +863,7 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
        if (on) {
                ret = m5mols_sensor_power(info, true);
                if (!ret)
-                       ret = m5mols_sensor_armboot(sd);
-               if (!ret)
-                       ret = m5mols_init_controls(info);
-               if (ret)
-                       return ret;
-
-               info->ffmt[M5MOLS_RESTYPE_MONITOR] =
-                       m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR];
-               info->ffmt[M5MOLS_RESTYPE_CAPTURE] =
-                       m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE];
+                       ret = m5mols_fw_start(sd);
                return ret;
        }
 
@@ -829,17 +874,14 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
                if (!ret)
                        ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
                if (!ret)
-                       ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS,
-                                       REG_AF_IDLE);
-               if (!ret)
-                       v4l2_info(sd, "Success soft-landing lens\n");
+                       ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
+                                              0xff, -1);
+               if (ret < 0)
+                       v4l2_warn(sd, "Soft landing lens failed\n");
        }
 
        ret = m5mols_sensor_power(info, false);
-       if (!ret) {
-               v4l2_ctrl_handler_free(&info->handle);
-               info->ctrl_sync = false;
-       }
+       info->ctrl_sync = 0;
 
        return ret;
 }
@@ -865,52 +907,33 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = {
        .log_status     = m5mols_log_status,
 };
 
+/*
+ * V4L2 subdev internal operations
+ */
+static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+       *format = m5mols_default_ffmt[0];
+       return 0;
+}
+
+static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
+       .open           = m5mols_open,
+};
+
 static const struct v4l2_subdev_ops m5mols_ops = {
        .core           = &m5mols_core_ops,
        .pad            = &m5mols_pad_ops,
        .video          = &m5mols_video_ops,
 };
 
-static void m5mols_irq_work(struct work_struct *work)
-{
-       struct m5mols_info *info =
-               container_of(work, struct m5mols_info, work_irq);
-       struct v4l2_subdev *sd = &info->sd;
-       u8 reg;
-       int ret;
-
-       if (!is_powered(info) ||
-                       m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
-               return;
-
-       switch (info->interrupt & REG_INT_MASK) {
-       case REG_INT_AF:
-               if (!is_available_af(info))
-                       break;
-               ret = m5mols_read_u8(sd, AF_STATUS, &reg);
-               v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
-                        reg == REG_AF_FAIL ? "Failed" :
-                        reg == REG_AF_SUCCESS ? "Success" :
-                        reg == REG_AF_IDLE ? "Idle" : "Busy");
-               break;
-       case REG_INT_CAPTURE:
-               if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags))
-                       wake_up_interruptible(&info->irq_waitq);
-
-               v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n");
-               break;
-       default:
-               v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg);
-               break;
-       };
-}
-
 static irqreturn_t m5mols_irq_handler(int irq, void *data)
 {
-       struct v4l2_subdev *sd = data;
-       struct m5mols_info *info = to_m5mols(sd);
+       struct m5mols_info *info = to_m5mols(data);
 
-       schedule_work(&info->work_irq);
+       atomic_set(&info->irq_done, 1);
+       wake_up_interruptible(&info->irq_waitq);
 
        return IRQ_HANDLED;
 }
@@ -961,7 +984,9 @@ static int __devinit m5mols_probe(struct i2c_client *client,
        sd = &info->sd;
        strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
        v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
+       sd->internal_ops = &m5mols_subdev_internal_ops;
        info->pad.flags = MEDIA_PAD_FL_SOURCE;
        ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
        if (ret < 0)
@@ -969,7 +994,6 @@ static int __devinit m5mols_probe(struct i2c_client *client,
        sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
 
        init_waitqueue_head(&info->irq_waitq);
-       INIT_WORK(&info->work_irq, m5mols_irq_work);
        ret = request_irq(client->irq, m5mols_irq_handler,
                          IRQF_TRIGGER_RISING, MODULE_NAME, sd);
        if (ret) {
@@ -977,7 +1001,20 @@ static int __devinit m5mols_probe(struct i2c_client *client,
                goto out_me;
        }
        info->res_type = M5MOLS_RESTYPE_MONITOR;
-       return 0;
+       info->ffmt[0] = m5mols_default_ffmt[0];
+       info->ffmt[1] = m5mols_default_ffmt[1];
+
+       ret = m5mols_sensor_power(info, true);
+       if (ret)
+               goto out_me;
+
+       ret = m5mols_fw_start(sd);
+       if (!ret)
+               ret = m5mols_init_controls(info);
+
+       m5mols_sensor_power(info, false);
+       if (!ret)
+               return 0;
 out_me:
        media_entity_cleanup(&sd->entity);
 out_reg:
@@ -995,6 +1032,7 @@ static int __devexit m5mols_remove(struct i2c_client *client)
        struct m5mols_info *info = to_m5mols(sd);
 
        v4l2_device_unregister_subdev(sd);
+       v4l2_ctrl_handler_free(sd->ctrl_handler);
        free_irq(client->irq, sd);
 
        regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
index c755bd6edfe9b0a485731e641766d39396356ee0..ae4aced0f9b23b0789c69647f2810c9cf98426a7 100644 (file)
  * There is many registers between customer version address and awb one. For
  * more specific contents, see definition if file m5mols.h.
  */
-#define CAT0_VER_CUSTOMER      0x00    /* customer version */
-#define CAT0_VER_PROJECT       0x01    /* project version */
-#define CAT0_VER_FIRMWARE      0x02    /* Firmware version */
-#define CAT0_VER_HARDWARE      0x04    /* Hardware version */
-#define CAT0_VER_PARAMETER     0x06    /* Parameter version */
-#define CAT0_VER_AWB           0x08    /* Auto WB version */
-#define CAT0_VER_STRING                0x0a    /* string including M-5MOLS */
-#define CAT0_SYSMODE           0x0b    /* SYSTEM mode register */
-#define CAT0_STATUS            0x0c    /* SYSTEM mode status register */
-#define CAT0_INT_FACTOR                0x10    /* interrupt pending register */
-#define CAT0_INT_ENABLE                0x11    /* interrupt enable register */
-
-#define SYSTEM_VER_CUSTOMER    I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1)
-#define SYSTEM_VER_PROJECT     I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1)
-#define SYSTEM_VER_FIRMWARE    I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2)
-#define SYSTEM_VER_HARDWARE    I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2)
-#define SYSTEM_VER_PARAMETER   I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2)
-#define SYSTEM_VER_AWB         I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2)
-
-#define SYSTEM_SYSMODE         I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1)
+#define SYSTEM_VER_CUSTOMER    I2C_REG(CAT_SYSTEM, 0x00, 1)
+#define SYSTEM_VER_PROJECT     I2C_REG(CAT_SYSTEM, 0x01, 1)
+#define SYSTEM_VER_FIRMWARE    I2C_REG(CAT_SYSTEM, 0x02, 2)
+#define SYSTEM_VER_HARDWARE    I2C_REG(CAT_SYSTEM, 0x04, 2)
+#define SYSTEM_VER_PARAMETER   I2C_REG(CAT_SYSTEM, 0x06, 2)
+#define SYSTEM_VER_AWB         I2C_REG(CAT_SYSTEM, 0x08, 2)
+
+#define SYSTEM_SYSMODE         I2C_REG(CAT_SYSTEM, 0x0b, 1)
 #define REG_SYSINIT            0x00    /* SYSTEM mode */
 #define REG_PARAMETER          0x01    /* PARAMETER mode */
 #define REG_MONITOR            0x02    /* MONITOR mode */
 #define REG_CAPTURE            0x03    /* CAPTURE mode */
 
 #define SYSTEM_CMD(__cmd)      I2C_REG(CAT_SYSTEM, cmd, 1)
-#define SYSTEM_VER_STRING      I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1)
+#define SYSTEM_VER_STRING      I2C_REG(CAT_SYSTEM, 0x0a, 1)
 #define REG_SAMSUNG_ELECTRO    "SE"    /* Samsung Electro-Mechanics */
 #define REG_SAMSUNG_OPTICS     "OP"    /* Samsung Fiber-Optics */
 #define REG_SAMSUNG_TECHWIN    "TB"    /* Samsung Techwin */
+/* SYSTEM mode status */
+#define SYSTEM_STATUS  I2C_REG(CAT_SYSTEM, 0x0c, 1)
 
-#define SYSTEM_INT_FACTOR      I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1)
-#define SYSTEM_INT_ENABLE      I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1)
+/* Interrupt pending register */
+#define SYSTEM_INT_FACTOR      I2C_REG(CAT_SYSTEM, 0x10, 1)
+/* interrupt enable register */
+#define SYSTEM_INT_ENABLE      I2C_REG(CAT_SYSTEM, 0x11, 1)
 #define REG_INT_MODE           (1 << 0)
 #define REG_INT_AF             (1 << 1)
 #define REG_INT_ZOOM           (1 << 2)
  * can handle with preview(MONITOR) resolution size/frame per second/interface
  * between the sensor and the Application Processor/even the image effect.
  */
-#define CAT1_DATA_INTERFACE    0x00    /* interface between sensor and AP */
-#define CAT1_MONITOR_SIZE      0x01    /* resolution at the MONITOR mode */
-#define CAT1_MONITOR_FPS       0x02    /* frame per second at this mode */
-#define CAT1_EFFECT            0x0b    /* image effects */
 
-#define PARM_MON_SIZE          I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1)
+/* Resolution in the MONITOR mode */
+#define PARM_MON_SIZE          I2C_REG(CAT_PARAM, 0x01, 1)
 
-#define PARM_MON_FPS           I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1)
+/* Frame rate */
+#define PARM_MON_FPS           I2C_REG(CAT_PARAM, 0x02, 1)
 #define REG_FPS_30             0x02
 
-#define PARM_INTERFACE         I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1)
+/* Video bus between the sensor and a host processor */
+#define PARM_INTERFACE         I2C_REG(CAT_PARAM, 0x00, 1)
 #define REG_INTERFACE_MIPI     0x02
 
-#define PARM_EFFECT            I2C_REG(CAT_PARAM, CAT1_EFFECT, 1)
+/* Image effects */
+#define PARM_EFFECT            I2C_REG(CAT_PARAM, 0x0b, 1)
 #define REG_EFFECT_OFF         0x00
 #define REG_EFFECT_NEGA                0x01
 #define REG_EFFECT_EMBOSS      0x06
  * another options like zoom/color effect(different with effect in PARAMETER
  * mode)/anti hand shaking algorithm.
  */
-#define CAT2_ZOOM              0x01    /* set the zoom position & execute */
-#define CAT2_ZOOM_STEP         0x03    /* set the zoom step */
-#define CAT2_CFIXB             0x09    /* CB value for color effect */
-#define CAT2_CFIXR             0x0a    /* CR value for color effect */
-#define CAT2_COLOR_EFFECT      0x0b    /* set on/off of color effect */
-#define CAT2_CHROMA_LVL                0x0f    /* set chroma level */
-#define CAT2_CHROMA_EN         0x10    /* set on/off of choroma */
-#define CAT2_EDGE_LVL          0x11    /* set sharpness level */
-#define CAT2_EDGE_EN           0x12    /* set on/off sharpness */
-#define CAT2_TONE_CTL          0x25    /* set tone color(contrast) */
-
-#define MON_ZOOM               I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1)
-
-#define MON_CFIXR              I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1)
-#define MON_CFIXB              I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1)
+
+/* Target digital zoom position */
+#define MON_ZOOM               I2C_REG(CAT_MONITOR, 0x01, 1)
+
+/* CR value for color effect */
+#define MON_CFIXR              I2C_REG(CAT_MONITOR, 0x0a, 1)
+/* CB value for color effect */
+#define MON_CFIXB              I2C_REG(CAT_MONITOR, 0x09, 1)
 #define REG_CFIXB_SEPIA                0xd8
 #define REG_CFIXR_SEPIA                0x18
 
-#define MON_EFFECT             I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1)
+#define MON_EFFECT             I2C_REG(CAT_MONITOR, 0x0b, 1)
 #define REG_COLOR_EFFECT_OFF   0x00
 #define REG_COLOR_EFFECT_ON    0x01
 
-#define MON_CHROMA_EN          I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1)
-#define MON_CHROMA_LVL         I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1)
+/* Chroma enable */
+#define MON_CHROMA_EN          I2C_REG(CAT_MONITOR, 0x10, 1)
+/* Chroma level */
+#define MON_CHROMA_LVL         I2C_REG(CAT_MONITOR, 0x0f, 1)
 #define REG_CHROMA_OFF         0x00
 #define REG_CHROMA_ON          0x01
 
-#define MON_EDGE_EN            I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1)
-#define MON_EDGE_LVL           I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1)
+/* Sharpness on/off */
+#define MON_EDGE_EN            I2C_REG(CAT_MONITOR, 0x12, 1)
+/* Sharpness level */
+#define MON_EDGE_LVL           I2C_REG(CAT_MONITOR, 0x11, 1)
 #define REG_EDGE_OFF           0x00
 #define REG_EDGE_ON            0x01
 
-#define MON_TONE_CTL           I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1)
+/* Set color tone (contrast) */
+#define MON_TONE_CTL           I2C_REG(CAT_MONITOR, 0x25, 1)
 
 /*
  * Category 3 - Auto Exposure
  * different. So, this category also provide getting the max/min values. And,
  * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
  */
-#define CAT3_AE_LOCK           0x00    /* locking Auto exposure */
-#define CAT3_AE_MODE           0x01    /* set AE mode, mode means range */
-#define CAT3_ISO               0x05    /* set ISO */
-#define CAT3_EV_PRESET_MONITOR 0x0a    /* EV(scenemode) preset for MONITOR */
-#define CAT3_EV_PRESET_CAPTURE 0x0b    /* EV(scenemode) preset for CAPTURE */
-#define CAT3_MANUAL_GAIN_MON   0x12    /* meteoring value for the MONITOR */
-#define CAT3_MAX_GAIN_MON      0x1a    /* max gain value for the MONITOR */
-#define CAT3_MANUAL_GAIN_CAP   0x26    /* meteoring value for the CAPTURE */
-#define CAT3_AE_INDEX          0x38    /* AE index */
-
-#define AE_LOCK                        I2C_REG(CAT_AE, CAT3_AE_LOCK, 1)
+
+/* Auto Exposure locking */
+#define AE_LOCK                        I2C_REG(CAT_AE, 0x00, 1)
 #define REG_AE_UNLOCK          0x00
 #define REG_AE_LOCK            0x01
 
-#define AE_MODE                        I2C_REG(CAT_AE, CAT3_AE_MODE, 1)
+/* Auto Exposure algorithm mode */
+#define AE_MODE                        I2C_REG(CAT_AE, 0x01, 1)
 #define REG_AE_OFF             0x00    /* AE off */
 #define REG_AE_ALL             0x01    /* calc AE in all block integral */
 #define REG_AE_CENTER          0x03    /* calc AE in center weighted */
 #define REG_AE_SPOT            0x06    /* calc AE in specific spot */
 
-#define AE_ISO                 I2C_REG(CAT_AE, CAT3_ISO, 1)
+#define AE_ISO                 I2C_REG(CAT_AE, 0x05, 1)
 #define REG_ISO_AUTO           0x00
 #define REG_ISO_50             0x01
 #define REG_ISO_100            0x02
 #define REG_ISO_400            0x04
 #define REG_ISO_800            0x05
 
-#define AE_EV_PRESET_MONITOR   I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1)
-#define AE_EV_PRESET_CAPTURE   I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1)
+/* EV (scenemode) preset for MONITOR */
+#define AE_EV_PRESET_MONITOR   I2C_REG(CAT_AE, 0x0a, 1)
+/* EV (scenemode) preset for CAPTURE */
+#define AE_EV_PRESET_CAPTURE   I2C_REG(CAT_AE, 0x0b, 1)
 #define REG_SCENE_NORMAL       0x00
 #define REG_SCENE_PORTRAIT     0x01
 #define REG_SCENE_LANDSCAPE    0x02
 #define REG_SCENE_TEXT         0x0c
 #define REG_SCENE_CANDLE       0x0d
 
-#define AE_MAN_GAIN_MON                I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2)
-#define AE_MAX_GAIN_MON                I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2)
-#define AE_MAN_GAIN_CAP                I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2)
+/* Manual gain in MONITOR mode */
+#define AE_MAN_GAIN_MON                I2C_REG(CAT_AE, 0x12, 2)
+/* Maximum gain in MONITOR mode */
+#define AE_MAX_GAIN_MON                I2C_REG(CAT_AE, 0x1a, 2)
+/* Manual gain in CAPTURE mode */
+#define AE_MAN_GAIN_CAP                I2C_REG(CAT_AE, 0x26, 2)
 
-#define AE_INDEX               I2C_REG(CAT_AE, CAT3_AE_INDEX, 1)
+#define AE_INDEX               I2C_REG(CAT_AE, 0x38, 1)
 #define REG_AE_INDEX_20_NEG    0x00
 #define REG_AE_INDEX_15_NEG    0x01
 #define REG_AE_INDEX_10_NEG    0x02
 
 /*
  * Category 6 - White Balance
- *
- * This category provide AWB locking/mode/preset/speed/gain bias, etc.
  */
-#define CAT6_AWB_LOCK          0x00    /* locking Auto Whitebalance */
-#define CAT6_AWB_MODE          0x02    /* set Auto or Manual */
-#define CAT6_AWB_MANUAL                0x03    /* set Manual(preset) value */
 
-#define AWB_LOCK               I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1)
+/* Auto Whitebalance locking */
+#define AWB_LOCK               I2C_REG(CAT_WB, 0x00, 1)
 #define REG_AWB_UNLOCK         0x00
 #define REG_AWB_LOCK           0x01
 
-#define AWB_MODE               I2C_REG(CAT_WB, CAT6_AWB_MODE, 1)
+#define AWB_MODE               I2C_REG(CAT_WB, 0x02, 1)
 #define REG_AWB_AUTO           0x01    /* AWB off */
 #define REG_AWB_PRESET         0x02    /* AWB preset */
 
-#define AWB_MANUAL             I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1)
+/* Manual WB (preset) */
+#define AWB_MANUAL             I2C_REG(CAT_WB, 0x03, 1)
 #define REG_AWB_INCANDESCENT   0x01
 #define REG_AWB_FLUORESCENT_1  0x02
 #define REG_AWB_FLUORESCENT_2  0x03
 /*
  * Category 7 - EXIF information
  */
-#define CAT7_INFO_EXPTIME_NU   0x00
-#define CAT7_INFO_EXPTIME_DE   0x04
-#define CAT7_INFO_TV_NU                0x08
-#define CAT7_INFO_TV_DE                0x0c
-#define CAT7_INFO_AV_NU                0x10
-#define CAT7_INFO_AV_DE                0x14
-#define CAT7_INFO_BV_NU                0x18
-#define CAT7_INFO_BV_DE                0x1c
-#define CAT7_INFO_EBV_NU       0x20
-#define CAT7_INFO_EBV_DE       0x24
-#define CAT7_INFO_ISO          0x28
-#define CAT7_INFO_FLASH                0x2a
-#define CAT7_INFO_SDR          0x2c
-#define CAT7_INFO_QVAL         0x2e
-
-#define EXIF_INFO_EXPTIME_NU   I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4)
-#define EXIF_INFO_EXPTIME_DE   I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4)
-#define EXIF_INFO_TV_NU                I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4)
-#define EXIF_INFO_TV_DE                I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4)
-#define EXIF_INFO_AV_NU                I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4)
-#define EXIF_INFO_AV_DE                I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4)
-#define EXIF_INFO_BV_NU                I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4)
-#define EXIF_INFO_BV_DE                I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4)
-#define EXIF_INFO_EBV_NU       I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4)
-#define EXIF_INFO_EBV_DE       I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4)
-#define EXIF_INFO_ISO          I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2)
-#define EXIF_INFO_FLASH                I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2)
-#define EXIF_INFO_SDR          I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2)
-#define EXIF_INFO_QVAL         I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2)
+#define EXIF_INFO_EXPTIME_NU   I2C_REG(CAT_EXIF, 0x00, 4)
+#define EXIF_INFO_EXPTIME_DE   I2C_REG(CAT_EXIF, 0x04, 4)
+#define EXIF_INFO_TV_NU                I2C_REG(CAT_EXIF, 0x08, 4)
+#define EXIF_INFO_TV_DE                I2C_REG(CAT_EXIF, 0x0c, 4)
+#define EXIF_INFO_AV_NU                I2C_REG(CAT_EXIF, 0x10, 4)
+#define EXIF_INFO_AV_DE                I2C_REG(CAT_EXIF, 0x14, 4)
+#define EXIF_INFO_BV_NU                I2C_REG(CAT_EXIF, 0x18, 4)
+#define EXIF_INFO_BV_DE                I2C_REG(CAT_EXIF, 0x1c, 4)
+#define EXIF_INFO_EBV_NU       I2C_REG(CAT_EXIF, 0x20, 4)
+#define EXIF_INFO_EBV_DE       I2C_REG(CAT_EXIF, 0x24, 4)
+#define EXIF_INFO_ISO          I2C_REG(CAT_EXIF, 0x28, 2)
+#define EXIF_INFO_FLASH                I2C_REG(CAT_EXIF, 0x2a, 2)
+#define EXIF_INFO_SDR          I2C_REG(CAT_EXIF, 0x2c, 2)
+#define EXIF_INFO_QVAL         I2C_REG(CAT_EXIF, 0x2e, 2)
 
 /*
  * Category 9 - Face Detection
  */
-#define CAT9_FD_CTL            0x00
-
-#define FD_CTL                 I2C_REG(CAT_FD, CAT9_FD_CTL, 1)
+#define FD_CTL                 I2C_REG(CAT_FD, 0x00, 1)
 #define BIT_FD_EN              0
 #define BIT_FD_DRAW_FACE_FRAME 4
 #define BIT_FD_DRAW_SMILE_LVL  6
 /*
  * Category A - Lens Parameter
  */
-#define CATA_AF_MODE           0x01
-#define CATA_AF_EXECUTE                0x02
-#define CATA_AF_STATUS         0x03
-#define CATA_AF_VERSION                0x0a
-
-#define AF_MODE                        I2C_REG(CAT_LENS, CATA_AF_MODE, 1)
+#define AF_MODE                        I2C_REG(CAT_LENS, 0x01, 1)
 #define REG_AF_NORMAL          0x00    /* Normal AF, one time */
 #define REG_AF_MACRO           0x01    /* Macro AF, one time */
 #define REG_AF_POWEROFF                0x07
 
-#define AF_EXECUTE             I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1)
+#define AF_EXECUTE             I2C_REG(CAT_LENS, 0x02, 1)
 #define REG_AF_STOP            0x00
 #define REG_AF_EXE_AUTO                0x01
 #define REG_AF_EXE_CAF         0x02
 
-#define AF_STATUS              I2C_REG(CAT_LENS, CATA_AF_STATUS, 1)
+#define AF_STATUS              I2C_REG(CAT_LENS, 0x03, 1)
 #define REG_AF_FAIL            0x00
 #define REG_AF_SUCCESS         0x02
 #define REG_AF_IDLE            0x04
 #define REG_AF_BUSY            0x05
 
-#define AF_VERSION             I2C_REG(CAT_LENS, CATA_AF_VERSION, 1)
+#define AF_VERSION             I2C_REG(CAT_LENS, 0x0a, 1)
 
 /*
  * Category B - CAPTURE Parameter
  */
-#define CATB_YUVOUT_MAIN       0x00
-#define CATB_MAIN_IMAGE_SIZE   0x01
-#define CATB_MCC_MODE          0x1d
-#define CATB_WDR_EN            0x2c
-#define CATB_LIGHT_CTRL                0x40
-#define CATB_FLASH_CTRL                0x41
-
-#define CAPP_YUVOUT_MAIN       I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1)
+#define CAPP_YUVOUT_MAIN       I2C_REG(CAT_CAPT_PARM, 0x00, 1)
 #define REG_YUV422             0x00
 #define REG_BAYER10            0x05
 #define REG_BAYER8             0x06
 #define REG_JPEG               0x10
 
-#define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1)
+#define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, 0x01, 1)
 
-#define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1)
+#define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
 #define REG_MCC_OFF            0x00
 #define REG_MCC_NORMAL         0x01
 
-#define CAPP_WDR_EN            I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1)
+#define CAPP_WDR_EN            I2C_REG(CAT_CAPT_PARM, 0x2c, 1)
 #define REG_WDR_OFF            0x00
 #define REG_WDR_ON             0x01
 #define REG_WDR_AUTO           0x02
 
-#define CAPP_LIGHT_CTRL                I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1)
+#define CAPP_LIGHT_CTRL                I2C_REG(CAT_CAPT_PARM, 0x40, 1)
 #define REG_LIGHT_OFF          0x00
 #define REG_LIGHT_ON           0x01
 #define REG_LIGHT_AUTO         0x02
 
-#define CAPP_FLASH_CTRL                I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1)
+#define CAPP_FLASH_CTRL                I2C_REG(CAT_CAPT_PARM, 0x41, 1)
 #define REG_FLASH_OFF          0x00
 #define REG_FLASH_ON           0x01
 #define REG_FLASH_AUTO         0x02
 /*
  * Category C - CAPTURE Control
  */
-#define CATC_CAP_MODE          0x00
-#define CATC_CAP_SEL_FRAME     0x06    /* It determines Single or Multi */
-#define CATC_CAP_START         0x09
-#define CATC_CAP_IMAGE_SIZE    0x0d
-#define CATC_CAP_THUMB_SIZE    0x11
-
-#define CAPC_MODE              I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1)
+#define CAPC_MODE              I2C_REG(CAT_CAPT_CTRL, 0x00, 1)
 #define REG_CAP_NONE           0x00
 #define REG_CAP_ANTI_SHAKE     0x02
 
-#define CAPC_SEL_FRAME         I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1)
+/* Select single- or multi-shot capture */
+#define CAPC_SEL_FRAME         I2C_REG(CAT_CAPT_CTRL, 0x06, 1)
 
-#define CAPC_START             I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1)
+#define CAPC_START             I2C_REG(CAT_CAPT_CTRL, 0x09, 1)
 #define REG_CAP_START_MAIN     0x01
 #define REG_CAP_START_THUMB    0x03
 
-#define CAPC_IMAGE_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4)
-#define CAPC_THUMB_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4)
+#define CAPC_IMAGE_SIZE                I2C_REG(CAT_CAPT_CTRL, 0x0d, 4)
+#define CAPC_THUMB_SIZE                I2C_REG(CAT_CAPT_CTRL, 0x11, 4)
 
 /*
  * Category F - Flash
  *
  * This mode provides functions about internal flash stuff and system startup.
  */
-#define CATF_CAM_START         0x12    /* It starts internal ARM core booting
-                                        * after power-up */
 
-#define FLASH_CAM_START                I2C_REG(CAT_FLASH, CATF_CAM_START, 1)
-#define REG_START_ARM_BOOT     0x01
+/* Starts internal ARM core booting after power-up */
+#define FLASH_CAM_START                I2C_REG(CAT_FLASH, 0x12, 1)
+#define REG_START_ARM_BOOT     0x01    /* write value */
+#define REG_IN_FLASH_MODE      0x00    /* read value */
 
 #endif /* M5MOLS_REG_H */
index 2c8fc0f6d690e41c1c22d7b4adeb350f7ac66a65..37d20e73908a24402a933740b68d4463532e64eb 100644 (file)
@@ -522,6 +522,15 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam)
  */
 static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
 {
+       /*
+        * The list-empty condition can hit us at resume time
+        * if the buffer list was empty when the system was suspended.
+        */
+       if (list_empty(&cam->buffers)) {
+               set_bit(CF_SG_RESTART, &cam->flags);
+               return;
+       }
+
        mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD);
        mcam_sg_next_buffer(cam);
        mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
@@ -566,6 +575,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
        } else {
                set_bit(CF_SG_RESTART, &cam->flags);
                singles++;
+               cam->vb_bufs[0] = NULL;
        }
        /*
         * Now we can give the completed frame back to user space.
@@ -661,10 +671,10 @@ static int mcam_ctlr_configure(struct mcam_camera *cam)
        unsigned long flags;
 
        spin_lock_irqsave(&cam->dev_lock, flags);
+       clear_bit(CF_SG_RESTART, &cam->flags);
        cam->dma_setup(cam);
        mcam_ctlr_image(cam);
        mcam_set_config_needed(cam, 0);
-       clear_bit(CF_SG_RESTART, &cam->flags);
        spin_unlock_irqrestore(&cam->dev_lock, flags);
        return 0;
 }
@@ -873,7 +883,8 @@ static int mcam_read_setup(struct mcam_camera *cam)
        mcam_reset_buffers(cam);
        mcam_ctlr_irq_enable(cam);
        cam->state = S_STREAMING;
-       mcam_ctlr_start(cam);
+       if (!test_bit(CF_SG_RESTART, &cam->flags))
+               mcam_ctlr_start(cam);
        spin_unlock_irqrestore(&cam->dev_lock, flags);
        return 0;
 }
@@ -1818,11 +1829,15 @@ void mccic_shutdown(struct mcam_camera *cam)
 
 void mccic_suspend(struct mcam_camera *cam)
 {
-       enum mcam_state cstate = cam->state;
+       mutex_lock(&cam->s_mutex);
+       if (cam->users > 0) {
+               enum mcam_state cstate = cam->state;
 
-       mcam_ctlr_stop_dma(cam);
-       mcam_ctlr_power_down(cam);
-       cam->state = cstate;
+               mcam_ctlr_stop_dma(cam);
+               mcam_ctlr_power_down(cam);
+               cam->state = cstate;
+       }
+       mutex_unlock(&cam->s_mutex);
 }
 
 int mccic_resume(struct mcam_camera *cam)
@@ -1839,8 +1854,15 @@ int mccic_resume(struct mcam_camera *cam)
        mutex_unlock(&cam->s_mutex);
 
        set_bit(CF_CONFIG_NEEDED, &cam->flags);
-       if (cam->state == S_STREAMING)
+       if (cam->state == S_STREAMING) {
+               /*
+                * If there was a buffer in the DMA engine at suspend
+                * time, put it back on the queue or we'll forget about it.
+                */
+               if (cam->buffer_mode == B_DMA_sg && cam->vb_bufs[0])
+                       list_add(&cam->vb_bufs[0]->queue, &cam->buffers);
                ret = mcam_read_setup(cam);
+       }
        return ret;
 }
 #endif /* CONFIG_PM */
index fb0b124b35f302529eadcc9f3eef85db3820a10a..0d64e2d7474a52eebc06bf1dd84314ba7d32d288 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/list.h>
+#include <linux/pm.h>
 
 #include "mcam-core.h"
 
@@ -310,10 +311,44 @@ static int mmpcam_platform_remove(struct platform_device *pdev)
        return mmpcam_remove(cam);
 }
 
+/*
+ * Suspend/resume support.
+ */
+#ifdef CONFIG_PM
+
+static int mmpcam_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct mmp_camera *cam = mmpcam_find_device(pdev);
+
+       if (state.event != PM_EVENT_SUSPEND)
+               return 0;
+       mccic_suspend(&cam->mcam);
+       return 0;
+}
+
+static int mmpcam_resume(struct platform_device *pdev)
+{
+       struct mmp_camera *cam = mmpcam_find_device(pdev);
+
+       /*
+        * Power up unconditionally just in case the core tries to
+        * touch a register even if nothing was active before; trust
+        * me, it's better this way.
+        */
+       mmpcam_power_up(&cam->mcam);
+       return mccic_resume(&cam->mcam);
+}
+
+#endif
+
 
 static struct platform_driver mmpcam_driver = {
        .probe          = mmpcam_probe,
        .remove         = mmpcam_platform_remove,
+#ifdef CONFIG_PM
+       .suspend        = mmpcam_suspend,
+       .resume         = mmpcam_resume,
+#endif
        .driver = {
                .name   = "mmp-camera",
                .owner  = THIS_MODULE
index e2b1029b16cdd24552123d67dfc4a44ef51a6359..097c9d3d04a8c581236a928d9eceeaed765d4d72 100644 (file)
@@ -109,14 +109,13 @@ static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
 
 static int reg_read(struct i2c_client *client, const u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
-       return data < 0 ? data : swab16(data);
+       return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int reg_write(struct i2c_client *client, const u8 reg,
                     const u16 data)
 {
-       return i2c_smbus_write_word_data(client, reg, swab16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int reg_set(struct i2c_client *client, const u8 reg,
index 398f96ffd35e88d212a8d39c8585decfc1d426d0..bee65bff46e8d5e25e94f49253d8b41484da3438 100644 (file)
 #define MT9M111_MAX_HEIGHT     1024
 #define MT9M111_MAX_WIDTH      1280
 
+struct mt9m111_context {
+       u16 read_mode;
+       u16 blanking_h;
+       u16 blanking_v;
+       u16 reducer_xzoom;
+       u16 reducer_yzoom;
+       u16 reducer_xsize;
+       u16 reducer_ysize;
+       u16 output_fmt_ctrl2;
+       u16 control;
+};
+
+static struct mt9m111_context context_a = {
+       .read_mode              = MT9M111_READ_MODE_A,
+       .blanking_h             = MT9M111_HORIZONTAL_BLANKING_A,
+       .blanking_v             = MT9M111_VERTICAL_BLANKING_A,
+       .reducer_xzoom          = MT9M111_REDUCER_XZOOM_A,
+       .reducer_yzoom          = MT9M111_REDUCER_YZOOM_A,
+       .reducer_xsize          = MT9M111_REDUCER_XSIZE_A,
+       .reducer_ysize          = MT9M111_REDUCER_YSIZE_A,
+       .output_fmt_ctrl2       = MT9M111_OUTPUT_FORMAT_CTRL2_A,
+       .control                = MT9M111_CTXT_CTRL_RESTART,
+};
+
+static struct mt9m111_context context_b = {
+       .read_mode              = MT9M111_READ_MODE_B,
+       .blanking_h             = MT9M111_HORIZONTAL_BLANKING_B,
+       .blanking_v             = MT9M111_VERTICAL_BLANKING_B,
+       .reducer_xzoom          = MT9M111_REDUCER_XZOOM_B,
+       .reducer_yzoom          = MT9M111_REDUCER_YZOOM_B,
+       .reducer_xsize          = MT9M111_REDUCER_XSIZE_B,
+       .reducer_ysize          = MT9M111_REDUCER_YSIZE_B,
+       .output_fmt_ctrl2       = MT9M111_OUTPUT_FORMAT_CTRL2_B,
+       .control                = MT9M111_CTXT_CTRL_RESTART |
+               MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |
+               MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |
+               MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |
+               MT9M111_CTXT_CTRL_HBLANK_SEL_B,
+};
+
 /* MT9M111 has only one fixed colorspace per pixelcode */
 struct mt9m111_datafmt {
        enum v4l2_mbus_pixelcode        code;
        enum v4l2_colorspace            colorspace;
 };
 
-/* Find a data format by a pixel code in an array */
-static const struct mt9m111_datafmt *mt9m111_find_datafmt(
-       enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt,
-       int n)
-{
-       int i;
-       for (i = 0; i < n; i++)
-               if (fmt[i].code == code)
-                       return fmt + i;
-
-       return NULL;
-}
-
 static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
        {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
        {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
@@ -173,27 +200,35 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
        {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
 };
 
-enum mt9m111_context {
-       HIGHPOWER = 0,
-       LOWPOWER,
-};
-
 struct mt9m111 {
        struct v4l2_subdev subdev;
        struct v4l2_ctrl_handler hdl;
        struct v4l2_ctrl *gain;
        int model;      /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
                         * from v4l2-chip-ident.h */
-       enum mt9m111_context context;
-       struct v4l2_rect rect;
+       struct mt9m111_context *ctx;
+       struct v4l2_rect rect;  /* cropping rectangle */
+       int width;              /* output */
+       int height;             /* sizes */
        struct mutex power_lock; /* lock to protect power_count */
        int power_count;
        const struct mt9m111_datafmt *fmt;
        int lastpage;   /* PageMap cache value */
        unsigned char datawidth;
-       unsigned int powered:1;
 };
 
+/* Find a data format by a pixel code */
+static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,
+                                               enum v4l2_mbus_pixelcode code)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)
+               if (mt9m111_colour_fmts[i].code == code)
+                       return mt9m111_colour_fmts + i;
+
+       return mt9m111->fmt;
+}
+
 static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
 {
        return container_of(i2c_get_clientdata(client), struct mt9m111, subdev);
@@ -211,7 +246,7 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg)
        if (page > 2)
                return -EINVAL;
 
-       ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
+       ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page);
        if (!ret)
                mt9m111->lastpage = page;
        return ret;
@@ -223,7 +258,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
 
        ret = reg_page_map_set(client, reg);
        if (!ret)
-               ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff));
+               ret = i2c_smbus_read_word_swapped(client, reg & 0xff);
 
        dev_dbg(&client->dev, "read  reg.%03x -> %04x\n", reg, ret);
        return ret;
@@ -236,8 +271,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
 
        ret = reg_page_map_set(client, reg);
        if (!ret)
-               ret = i2c_smbus_write_word_data(client, reg & 0xff,
-                                               swab16(data));
+               ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data);
        dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
        return ret;
 }
@@ -276,76 +310,63 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
 }
 
 static int mt9m111_set_context(struct mt9m111 *mt9m111,
-                              enum mt9m111_context ctxt)
+                              struct mt9m111_context *ctx)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
-               | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
-               | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
-               | MT9M111_CTXT_CTRL_VBLANK_SEL_B
-               | MT9M111_CTXT_CTRL_HBLANK_SEL_B;
-       int valA = MT9M111_CTXT_CTRL_RESTART;
-
-       if (ctxt == HIGHPOWER)
-               return reg_write(CONTEXT_CONTROL, valB);
-       else
-               return reg_write(CONTEXT_CONTROL, valA);
+       return reg_write(CONTEXT_CONTROL, ctx->control);
 }
 
-static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
-                             struct v4l2_rect *rect)
+static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,
+                       struct mt9m111_context *ctx, struct v4l2_rect *rect,
+                       unsigned int width, unsigned int height)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       int ret, is_raw_format;
-       int width = rect->width;
-       int height = rect->height;
+       int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, rect->width);
+       if (!ret)
+               ret = mt9m111_reg_write(client, ctx->reducer_yzoom, rect->height);
+       if (!ret)
+               ret = mt9m111_reg_write(client, ctx->reducer_xsize, width);
+       if (!ret)
+               ret = mt9m111_reg_write(client, ctx->reducer_ysize, height);
+       return ret;
+}
 
-       if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
-           mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE)
-               is_raw_format = 1;
-       else
-               is_raw_format = 0;
+static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,
+                       int width, int height, enum v4l2_mbus_pixelcode code)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+       int ret;
 
        ret = reg_write(COLUMN_START, rect->left);
        if (!ret)
                ret = reg_write(ROW_START, rect->top);
 
-       if (is_raw_format) {
-               if (!ret)
-                       ret = reg_write(WINDOW_WIDTH, width);
-               if (!ret)
-                       ret = reg_write(WINDOW_HEIGHT, height);
-       } else {
-               if (!ret)
-                       ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH);
-               if (!ret)
-                       ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
-               if (!ret)
-                       ret = reg_write(REDUCER_XSIZE_B, width);
-               if (!ret)
-                       ret = reg_write(REDUCER_YSIZE_B, height);
-               if (!ret)
-                       ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
-               if (!ret)
-                       ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
+       if (!ret)
+               ret = reg_write(WINDOW_WIDTH, rect->width);
+       if (!ret)
+               ret = reg_write(WINDOW_HEIGHT, rect->height);
+
+       if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+               /* IFP in use, down-scaling possible */
                if (!ret)
-                       ret = reg_write(REDUCER_XSIZE_A, width);
+                       ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,
+                                                    rect, width, height);
                if (!ret)
-                       ret = reg_write(REDUCER_YSIZE_A, height);
+                       ret = mt9m111_setup_rect_ctx(mt9m111, &context_a,
+                                                    rect, width, height);
        }
 
+       dev_dbg(&client->dev, "%s(%x): %ux%u@%u:%u -> %ux%u = %d\n",
+               __func__, code, rect->width, rect->height, rect->left, rect->top,
+               width, height, ret);
+
        return ret;
 }
 
 static int mt9m111_enable(struct mt9m111 *mt9m111)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       int ret;
-
-       ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE);
-       if (!ret)
-               mt9m111->powered = 1;
-       return ret;
+       return reg_write(RESET, MT9M111_RESET_CHIP_ENABLE);
 }
 
 static int mt9m111_reset(struct mt9m111 *mt9m111)
@@ -363,43 +384,41 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
        return ret;
 }
 
-static int mt9m111_make_rect(struct mt9m111 *mt9m111,
-                            struct v4l2_rect *rect)
+static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
+       struct v4l2_rect rect = a->c;
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+       int width, height;
+       int ret;
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
            mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
                /* Bayer format - even size lengths */
-               rect->width     = ALIGN(rect->width, 2);
-               rect->height    = ALIGN(rect->height, 2);
+               rect.width      = ALIGN(rect.width, 2);
+               rect.height     = ALIGN(rect.height, 2);
                /* Let the user play with the starting pixel */
        }
 
        /* FIXME: the datasheet doesn't specify minimum sizes */
-       soc_camera_limit_side(&rect->left, &rect->width,
+       soc_camera_limit_side(&rect.left, &rect.width,
                     MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH);
 
-       soc_camera_limit_side(&rect->top, &rect->height,
+       soc_camera_limit_side(&rect.top, &rect.height,
                     MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT);
 
-       return mt9m111_setup_rect(mt9m111, rect);
-}
-
-static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
-{
-       struct v4l2_rect rect = a->c;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-       int ret;
-
-       dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
-               __func__, rect.left, rect.top, rect.width, rect.height);
+       width = min(mt9m111->width, rect.width);
+       height = min(mt9m111->height, rect.height);
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       ret = mt9m111_make_rect(mt9m111, &rect);
-       if (!ret)
+       ret = mt9m111_setup_geometry(mt9m111, &rect, width, height, mt9m111->fmt->code);
+       if (!ret) {
                mt9m111->rect = rect;
+               mt9m111->width = width;
+               mt9m111->height = height;
+       }
+
        return ret;
 }
 
@@ -434,8 +453,8 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
 {
        struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
 
-       mf->width       = mt9m111->rect.width;
-       mf->height      = mt9m111->rect.height;
+       mf->width       = mt9m111->width;
+       mf->height      = mt9m111->height;
        mf->code        = mt9m111->fmt->code;
        mf->colorspace  = mt9m111->fmt->colorspace;
        mf->field       = V4L2_FIELD_NONE;
@@ -504,46 +523,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
                return -EINVAL;
        }
 
-       ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2,
-                      mask_outfmt2);
+       ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
+                              data_outfmt2, mask_outfmt2);
        if (!ret)
-               ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2,
-                              mask_outfmt2);
-
-       return ret;
-}
-
-static int mt9m111_s_fmt(struct v4l2_subdev *sd,
-                        struct v4l2_mbus_framefmt *mf)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       const struct mt9m111_datafmt *fmt;
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-       struct v4l2_rect rect = {
-               .left   = mt9m111->rect.left,
-               .top    = mt9m111->rect.top,
-               .width  = mf->width,
-               .height = mf->height,
-       };
-       int ret;
-
-       fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
-                                  ARRAY_SIZE(mt9m111_colour_fmts));
-       if (!fmt)
-               return -EINVAL;
-
-       dev_dbg(&client->dev,
-               "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
-               mf->code, rect.left, rect.top, rect.width, rect.height);
-
-       ret = mt9m111_make_rect(mt9m111, &rect);
-       if (!ret)
-               ret = mt9m111_set_pixfmt(mt9m111, mf->code);
-       if (!ret) {
-               mt9m111->rect   = rect;
-               mt9m111->fmt    = fmt;
-               mf->colorspace  = fmt->colorspace;
-       }
+               ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,
+                                      data_outfmt2, mask_outfmt2);
 
        return ret;
 }
@@ -551,42 +535,71 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
 static int mt9m111_try_fmt(struct v4l2_subdev *sd,
                           struct v4l2_mbus_framefmt *mf)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
        const struct mt9m111_datafmt *fmt;
-       bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
-               mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
-
-       fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
-                                  ARRAY_SIZE(mt9m111_colour_fmts));
-       if (!fmt) {
-               fmt = mt9m111->fmt;
-               mf->code = fmt->code;
-       }
+       struct v4l2_rect *rect = &mt9m111->rect;
+       bool bayer;
+
+       fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+
+       bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+               fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
 
        /*
         * With Bayer format enforce even side lengths, but let the user play
         * with the starting pixel
         */
+       if (bayer) {
+               rect->width = ALIGN(rect->width, 2);
+               rect->height = ALIGN(rect->height, 2);
+       }
 
-       if (mf->height > MT9M111_MAX_HEIGHT)
-               mf->height = MT9M111_MAX_HEIGHT;
-       else if (mf->height < 2)
-               mf->height = 2;
-       else if (bayer)
-               mf->height = ALIGN(mf->height, 2);
+       if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+               /* IFP bypass mode, no scaling */
+               mf->width = rect->width;
+               mf->height = rect->height;
+       } else {
+               /* No upscaling */
+               if (mf->width > rect->width)
+                       mf->width = rect->width;
+               if (mf->height > rect->height)
+                       mf->height = rect->height;
+       }
 
-       if (mf->width > MT9M111_MAX_WIDTH)
-               mf->width = MT9M111_MAX_WIDTH;
-       else if (mf->width < 2)
-               mf->width = 2;
-       else if (bayer)
-               mf->width = ALIGN(mf->width, 2);
+       dev_dbg(&client->dev, "%s(): %ux%u, code=%x\n", __func__,
+               mf->width, mf->height, fmt->code);
 
+       mf->code = fmt->code;
        mf->colorspace = fmt->colorspace;
 
        return 0;
 }
 
+static int mt9m111_s_fmt(struct v4l2_subdev *sd,
+                        struct v4l2_mbus_framefmt *mf)
+{
+       const struct mt9m111_datafmt *fmt;
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+       struct v4l2_rect *rect = &mt9m111->rect;
+       int ret;
+
+       mt9m111_try_fmt(sd, mf);
+       fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+       /* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */
+
+       ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);
+       if (!ret)
+               ret = mt9m111_set_pixfmt(mt9m111, mf->code);
+       if (!ret) {
+               mt9m111->width  = mf->width;
+               mt9m111->height = mf->height;
+               mt9m111->fmt    = fmt;
+       }
+
+       return ret;
+}
+
 static int mt9m111_g_chip_ident(struct v4l2_subdev *sd,
                                struct v4l2_dbg_chip_ident *id)
 {
@@ -650,17 +663,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
-       if (mt9m111->context == HIGHPOWER) {
-               if (flip)
-                       ret = reg_set(READ_MODE_B, mask);
-               else
-                       ret = reg_clear(READ_MODE_B, mask);
-       } else {
-               if (flip)
-                       ret = reg_set(READ_MODE_A, mask);
-               else
-                       ret = reg_clear(READ_MODE_A, mask);
-       }
+       if (flip)
+               ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);
+       else
+               ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);
 
        return ret;
 }
@@ -738,30 +744,39 @@ static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 
 static int mt9m111_suspend(struct mt9m111 *mt9m111)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+       int ret;
+
        v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
 
-       return 0;
+       ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+       if (!ret)
+               ret = reg_set(RESET, MT9M111_RESET_RESET_SOC |
+                             MT9M111_RESET_OUTPUT_DISABLE |
+                             MT9M111_RESET_ANALOG_STANDBY);
+       if (!ret)
+               ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
+
+       return ret;
 }
 
 static void mt9m111_restore_state(struct mt9m111 *mt9m111)
 {
-       mt9m111_set_context(mt9m111, mt9m111->context);
+       mt9m111_set_context(mt9m111, mt9m111->ctx);
        mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
-       mt9m111_setup_rect(mt9m111, &mt9m111->rect);
+       mt9m111_setup_geometry(mt9m111, &mt9m111->rect,
+                       mt9m111->width, mt9m111->height, mt9m111->fmt->code);
        v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_resume(struct mt9m111 *mt9m111)
 {
-       int ret = 0;
+       int ret = mt9m111_enable(mt9m111);
+       if (!ret)
+               ret = mt9m111_reset(mt9m111);
+       if (!ret)
+               mt9m111_restore_state(mt9m111);
 
-       if (mt9m111->powered) {
-               ret = mt9m111_enable(mt9m111);
-               if (!ret)
-                       ret = mt9m111_reset(mt9m111);
-               if (!ret)
-                       mt9m111_restore_state(mt9m111);
-       }
        return ret;
 }
 
@@ -770,12 +785,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
        int ret;
 
-       mt9m111->context = HIGHPOWER;
+       /* Default HIGHPOWER context */
+       mt9m111->ctx = &context_b;
        ret = mt9m111_enable(mt9m111);
        if (!ret)
                ret = mt9m111_reset(mt9m111);
        if (!ret)
-               ret = mt9m111_set_context(mt9m111, mt9m111->context);
+               ret = mt9m111_set_context(mt9m111, mt9m111->ctx);
        if (ret)
                dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
        return ret;
index 73c068993f050cce24eb408d2cbf7e745791c667..93c3ec7426e85ce14b83d8380c7c008abeb5505c 100644 (file)
@@ -132,13 +132,12 @@ static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
 
 static int mt9p031_read(struct i2c_client *client, u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
-       return data < 0 ? data : be16_to_cpu(data);
+       return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
 {
-       return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
index 08074b8a2736ca75a8bcdd6a26512536e584cf36..cd81d04a529e2ec9eb1d10fd9eb2c80f502830c4 100644 (file)
@@ -133,13 +133,12 @@ static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
 
 static int mt9t001_read(struct i2c_client *client, u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
-       return data < 0 ? data : be16_to_cpu(data);
+       return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
 {
-       return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
index 0e78477452ffb81bf5a09a781d9b68326b61e345..84add1aef13955941a1969d7dabec019148d7a51 100644 (file)
@@ -90,14 +90,13 @@ static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
 
 static int reg_read(struct i2c_client *client, const u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
-       return data < 0 ? data : swab16(data);
+       return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int reg_write(struct i2c_client *client, const u8 reg,
                     const u16 data)
 {
-       return i2c_smbus_write_word_data(client, reg, swab16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int reg_set(struct i2c_client *client, const u8 reg,
index 690ee0d42eebbcbb8aaf7374ca49a7302716180f..944940758fa3094d6ec0d5213342fc533d97a240 100644 (file)
@@ -130,14 +130,13 @@ static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
 
 static int reg_read(struct i2c_client *client, const u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
-       return data < 0 ? data : swab16(data);
+       return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int reg_write(struct i2c_client *client, const u8 reg,
                     const u16 data)
 {
-       return i2c_smbus_write_word_data(client, reg, swab16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int reg_set(struct i2c_client *client, const u8 reg,
index f080c162123f3ee0de1d0b532fc74a96d760b846..d90b982cc218d4adf5874494f2a3203fbd8bc43d 100644 (file)
@@ -139,10 +139,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
 
 static int mt9v032_read(struct i2c_client *client, const u8 reg)
 {
-       s32 data = i2c_smbus_read_word_data(client, reg);
+       s32 data = i2c_smbus_read_word_swapped(client, reg);
        dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
-               swab16(data), reg);
-       return data < 0 ? data : swab16(data);
+               data, reg);
+       return data;
 }
 
 static int mt9v032_write(struct i2c_client *client, const u8 reg,
@@ -150,7 +150,7 @@ static int mt9v032_write(struct i2c_client *client, const u8 reg,
 {
        dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
                data, reg);
-       return i2c_smbus_write_word_data(client, reg, swab16(data));
+       return i2c_smbus_write_word_swapped(client, reg, data);
 }
 
 static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
index 18e94c7d2be83e1668bdf6c6664ed50907761d40..055d11ddb0388aa6f3f1b2bb7244427d730c849e 100644 (file)
@@ -487,7 +487,7 @@ static int mx1_camera_set_crop(struct soc_camera_device *icd,
        return v4l2_subdev_call(sd, video, s_crop, a);
 }
 
-static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
index a803d9ea8fd61df40b2061a1423222435573e564..04aab0c538aa75c3e22da8338080ebe0a1890b57 100644 (file)
 
 #define MAX_VIDEO_MEM  16
 
+struct mx2_prp_cfg {
+       int channel;
+       u32 in_fmt;
+       u32 out_fmt;
+       u32 src_pixel;
+       u32 ch1_pixel;
+       u32 irq_flags;
+};
+
+/* prp configuration for a client-host fmt pair */
+struct mx2_fmt_cfg {
+       enum v4l2_mbus_pixelcode        in_fmt;
+       u32                             out_fmt;
+       struct mx2_prp_cfg              cfg;
+};
+
 struct mx2_camera_dev {
        struct device           *dev;
        struct soc_camera_host  soc_host;
@@ -241,6 +257,8 @@ struct mx2_camera_dev {
        void                    *discard_buffer;
        dma_addr_t              discard_buffer_dma;
        size_t                  discard_size;
+       struct mx2_fmt_cfg      *emma_prp;
+       u32                     frame_count;
 };
 
 /* buffer for one video frame */
@@ -253,6 +271,59 @@ struct mx2_buffer {
        int bufnum;
 };
 
+static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
+       /*
+        * This is a generic configuration which is valid for most
+        * prp input-output format combinations.
+        * We set the incomming and outgoing pixelformat to a
+        * 16 Bit wide format and adjust the bytesperline
+        * accordingly. With this configuration the inputdata
+        * will not be changed by the emma and could be any type
+        * of 16 Bit Pixelformat.
+        */
+       {
+               .in_fmt         = 0,
+               .out_fmt        = 0,
+               .cfg            = {
+                       .channel        = 1,
+                       .in_fmt         = PRP_CNTL_DATA_IN_RGB16,
+                       .out_fmt        = PRP_CNTL_CH1_OUT_RGB16,
+                       .src_pixel      = 0x2ca00565, /* RGB565 */
+                       .ch1_pixel      = 0x2ca00565, /* RGB565 */
+                       .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
+                                               PRP_INTR_CH1FC | PRP_INTR_LBOVF,
+               }
+       },
+       {
+               .in_fmt         = V4L2_MBUS_FMT_YUYV8_2X8,
+               .out_fmt        = V4L2_PIX_FMT_YUV420,
+               .cfg            = {
+                       .channel        = 2,
+                       .in_fmt         = PRP_CNTL_DATA_IN_YUV422,
+                       .out_fmt        = PRP_CNTL_CH2_OUT_YUV420,
+                       .src_pixel      = 0x22000888, /* YUV422 (YUYV) */
+                       .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
+                                       PRP_INTR_CH2FC | PRP_INTR_LBOVF |
+                                       PRP_INTR_CH2OVF,
+               }
+       },
+};
+
+static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
+                                       enum v4l2_mbus_pixelcode in_fmt,
+                                       u32 out_fmt)
+{
+       int i;
+
+       for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++)
+               if ((mx27_emma_prp_table[i].in_fmt == in_fmt) &&
+                               (mx27_emma_prp_table[i].out_fmt == out_fmt)) {
+                       return &mx27_emma_prp_table[i];
+               }
+       /* If no match return the most generic configuration */
+       return &mx27_emma_prp_table[0];
+};
+
 static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
 {
        unsigned long flags;
@@ -301,6 +372,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
        writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
 
        pcdev->icd = icd;
+       pcdev->frame_count = 0;
 
        dev_info(icd->parent, "Camera driver attached to camera %d\n",
                 icd->devnum);
@@ -719,55 +791,77 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
        struct soc_camera_host *ici =
                to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
+       struct mx2_fmt_cfg *prp = pcdev->emma_prp;
+       u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
+
+       if (prp->cfg.channel == 1) {
+               writel(pcdev->discard_buffer_dma,
+                               pcdev->base_emma + PRP_DEST_RGB1_PTR);
+               writel(pcdev->discard_buffer_dma,
+                               pcdev->base_emma + PRP_DEST_RGB2_PTR);
+
+               writel(PRP_CNTL_CH1EN |
+                               PRP_CNTL_CSIEN |
+                               prp->cfg.in_fmt |
+                               prp->cfg.out_fmt |
+                               PRP_CNTL_CH1_LEN |
+                               PRP_CNTL_CH1BYP |
+                               PRP_CNTL_CH1_TSKIP(0) |
+                               PRP_CNTL_IN_TSKIP(0),
+                               pcdev->base_emma + PRP_CNTL);
+
+               writel((icd->user_width << 16) | icd->user_height,
+                       pcdev->base_emma + PRP_SRC_FRAME_SIZE);
+               writel((icd->user_width << 16) | icd->user_height,
+                       pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
+               writel(bytesperline,
+                       pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
+               writel(prp->cfg.src_pixel,
+                       pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
+               writel(prp->cfg.ch1_pixel,
+                       pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
+       } else { /* channel 2 */
+               writel(pcdev->discard_buffer_dma,
+                       pcdev->base_emma + PRP_DEST_Y_PTR);
+               writel(pcdev->discard_buffer_dma,
+                       pcdev->base_emma + PRP_SOURCE_Y_PTR);
+
+               if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
+                       writel(pcdev->discard_buffer_dma + imgsize,
+                               pcdev->base_emma + PRP_DEST_CB_PTR);
+                       writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
+                               pcdev->base_emma + PRP_DEST_CR_PTR);
+                       writel(pcdev->discard_buffer_dma + imgsize,
+                               pcdev->base_emma + PRP_SOURCE_CB_PTR);
+                       writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
+                               pcdev->base_emma + PRP_SOURCE_CR_PTR);
+               }
 
-       writel(pcdev->discard_buffer_dma,
-                       pcdev->base_emma + PRP_DEST_RGB1_PTR);
-       writel(pcdev->discard_buffer_dma,
-                       pcdev->base_emma + PRP_DEST_RGB2_PTR);
-
-       /*
-        * We only use the EMMA engine to get rid of the broken
-        * DMA Engine. No color space consversion at the moment.
-        * We set the incomming and outgoing pixelformat to an
-        * 16 Bit wide format and adjust the bytesperline
-        * accordingly. With this configuration the inputdata
-        * will not be changed by the emma and could be any type
-        * of 16 Bit Pixelformat.
-        */
-       writel(PRP_CNTL_CH1EN |
+               writel(PRP_CNTL_CH2EN |
                        PRP_CNTL_CSIEN |
-                       PRP_CNTL_DATA_IN_RGB16 |
-                       PRP_CNTL_CH1_OUT_RGB16 |
-                       PRP_CNTL_CH1_LEN |
-                       PRP_CNTL_CH1BYP |
-                       PRP_CNTL_CH1_TSKIP(0) |
+                       prp->cfg.in_fmt |
+                       prp->cfg.out_fmt |
+                       PRP_CNTL_CH2_LEN |
+                       PRP_CNTL_CH2_TSKIP(0) |
                        PRP_CNTL_IN_TSKIP(0),
                        pcdev->base_emma + PRP_CNTL);
 
-       writel(((bytesperline >> 1) << 16) | icd->user_height,
+               writel((icd->user_width << 16) | icd->user_height,
                        pcdev->base_emma + PRP_SRC_FRAME_SIZE);
-       writel(((bytesperline >> 1) << 16) | icd->user_height,
-                       pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
-       writel(bytesperline,
-                       pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
-       writel(0x2ca00565, /* RGB565 */
+
+               writel((icd->user_width << 16) | icd->user_height,
+                       pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
+
+               writel(prp->cfg.src_pixel,
                        pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
-       writel(0x2ca00565, /* RGB565 */
-                       pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
+
+       }
 
        /* Enable interrupts */
-       writel(PRP_INTR_RDERR |
-                       PRP_INTR_CH1WERR |
-                       PRP_INTR_CH2WERR |
-                       PRP_INTR_CH1FC |
-                       PRP_INTR_CH2FC |
-                       PRP_INTR_LBOVF |
-                       PRP_INTR_CH2OVF,
-                       pcdev->base_emma + PRP_INTR_CNTL);
+       writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL);
 }
 
-static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
-               __u32 pixfmt)
+static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -911,9 +1005,58 @@ static int mx2_camera_set_crop(struct soc_camera_device *icd,
        return ret;
 }
 
+static int mx2_camera_get_formats(struct soc_camera_device *icd,
+                                 unsigned int idx,
+                                 struct soc_camera_format_xlate *xlate)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       const struct soc_mbus_pixelfmt *fmt;
+       struct device *dev = icd->parent;
+       enum v4l2_mbus_pixelcode code;
+       int ret, formats = 0;
+
+       ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+       if (ret < 0)
+               /* no more formats */
+               return 0;
+
+       fmt = soc_mbus_get_fmtdesc(code);
+       if (!fmt) {
+               dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
+               return 0;
+       }
+
+       if (code == V4L2_MBUS_FMT_YUYV8_2X8) {
+               formats++;
+               if (xlate) {
+                       /*
+                        * CH2 can output YUV420 which is a standard format in
+                        * soc_mediabus.c
+                        */
+                       xlate->host_fmt =
+                               soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8);
+                       xlate->code     = code;
+                       dev_dbg(dev, "Providing host format %s for sensor code %d\n",
+                              xlate->host_fmt->name, code);
+                       xlate++;
+               }
+       }
+
+       /* Generic pass-trough */
+       formats++;
+       if (xlate) {
+               xlate->host_fmt = fmt;
+               xlate->code     = code;
+               xlate++;
+       }
+       return formats;
+}
+
 static int mx2_camera_set_fmt(struct soc_camera_device *icd,
                               struct v4l2_format *f)
 {
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct mx2_camera_dev *pcdev = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
        struct v4l2_pix_format *pix = &f->fmt.pix;
@@ -946,6 +1089,10 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd,
        pix->colorspace         = mf.colorspace;
        icd->current_fmt        = xlate;
 
+       if (mx27_camera_emma(pcdev))
+               pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code,
+                                               xlate->host_fmt->fourcc);
+
        return 0;
 }
 
@@ -1011,7 +1158,12 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
 
        if (mf.field == V4L2_FIELD_ANY)
                mf.field = V4L2_FIELD_NONE;
-       if (mf.field != V4L2_FIELD_NONE) {
+       /*
+        * Driver supports interlaced images provided they have
+        * both fields so that they can be processed as if they
+        * were progressive.
+        */
+       if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) {
                dev_err(icd->parent, "Field type %d unsupported.\n",
                                mf.field);
                return -EINVAL;
@@ -1173,6 +1325,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
        .remove         = mx2_camera_remove_device,
        .set_fmt        = mx2_camera_set_fmt,
        .set_crop       = mx2_camera_set_crop,
+       .get_formats    = mx2_camera_get_formats,
        .try_fmt        = mx2_camera_try_fmt,
        .init_videobuf  = mx2_camera_init_videobuf,
        .reqbufs        = mx2_camera_reqbufs,
@@ -1184,6 +1337,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
 static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
                int bufnum, int state)
 {
+       u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
+       struct mx2_fmt_cfg *prp = pcdev->emma_prp;
        struct mx2_buffer *buf;
        struct videobuf_buffer *vb;
        unsigned long phys;
@@ -1197,12 +1352,22 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
                vb = &buf->vb;
 #ifdef DEBUG
                phys = videobuf_to_dma_contig(vb);
-               if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum)
-                               != phys) {
-                       dev_err(pcdev->dev, "%p != %p\n", phys,
-                                       readl(pcdev->base_emma +
-                                               PRP_DEST_RGB1_PTR +
-                                               4 * bufnum));
+               if (prp->cfg.channel == 1) {
+                       if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR +
+                               4 * bufnum) != phys) {
+                               dev_err(pcdev->dev, "%p != %p\n", phys,
+                                               readl(pcdev->base_emma +
+                                                       PRP_DEST_RGB1_PTR +
+                                                       4 * bufnum));
+                       }
+               } else {
+                       if (readl(pcdev->base_emma + PRP_DEST_Y_PTR -
+                               0x14 * bufnum) != phys) {
+                               dev_err(pcdev->dev, "%p != %p\n", phys,
+                                               readl(pcdev->base_emma +
+                                                       PRP_DEST_Y_PTR -
+                                                       0x14 * bufnum));
+                       }
                }
 #endif
                dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb,
@@ -1211,14 +1376,29 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
                list_del(&vb->queue);
                vb->state = state;
                do_gettimeofday(&vb->ts);
-               vb->field_count++;
+               vb->field_count = pcdev->frame_count * 2;
+               pcdev->frame_count++;
 
                wake_up(&vb->done);
        }
 
        if (list_empty(&pcdev->capture)) {
-               writel(pcdev->discard_buffer_dma, pcdev->base_emma +
-                               PRP_DEST_RGB1_PTR + 4 * bufnum);
+               if (prp->cfg.channel == 1) {
+                       writel(pcdev->discard_buffer_dma, pcdev->base_emma +
+                                       PRP_DEST_RGB1_PTR + 4 * bufnum);
+               } else {
+                       writel(pcdev->discard_buffer_dma, pcdev->base_emma +
+                                               PRP_DEST_Y_PTR -
+                                               0x14 * bufnum);
+                       if (prp->out_fmt == V4L2_PIX_FMT_YUV420) {
+                               writel(pcdev->discard_buffer_dma + imgsize,
+                                      pcdev->base_emma + PRP_DEST_CB_PTR -
+                                      0x14 * bufnum);
+                               writel(pcdev->discard_buffer_dma +
+                                      ((5 * imgsize) / 4), pcdev->base_emma +
+                                      PRP_DEST_CR_PTR - 0x14 * bufnum);
+                       }
+               }
                return;
        }
 
@@ -1233,7 +1413,18 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
        vb->state = VIDEOBUF_ACTIVE;
 
        phys = videobuf_to_dma_contig(vb);
-       writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
+       if (prp->cfg.channel == 1) {
+               writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
+       } else {
+               writel(phys, pcdev->base_emma +
+                               PRP_DEST_Y_PTR - 0x14 * bufnum);
+               if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
+                       writel(phys + imgsize, pcdev->base_emma +
+                                       PRP_DEST_CB_PTR - 0x14 * bufnum);
+                       writel(phys + ((5 * imgsize) / 4), pcdev->base_emma +
+                                       PRP_DEST_CR_PTR - 0x14 * bufnum);
+               }
+       }
 }
 
 static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
@@ -1253,10 +1444,12 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
                 * the next one.
                 */
                cntl = readl(pcdev->base_emma + PRP_CNTL);
-               writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL);
+               writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN),
+                      pcdev->base_emma + PRP_CNTL);
                writel(cntl, pcdev->base_emma + PRP_CNTL);
        }
-       if ((status & (3 << 5)) == (3 << 5)
+       if ((((status & (3 << 5)) == (3 << 5)) ||
+               ((status & (3 << 3)) == (3 << 3)))
                        && !list_empty(&pcdev->active_bufs)) {
                /*
                 * Both buffers have triggered, process the one we're expecting
@@ -1267,9 +1460,9 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
                mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE);
                status &= ~(1 << (6 - buf->bufnum)); /* mark processed */
        }
-       if (status & (1 << 6))
+       if ((status & (1 << 6)) || (status & (1 << 4)))
                mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE);
-       if (status & (1 << 5))
+       if ((status & (1 << 5)) || (status & (1 << 3)))
                mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE);
 
        writel(status, pcdev->base_emma + PRP_INTRSTATUS);
index f96f92f00f92f2e20de5a629238f55543006bf83..0cb461dd396af39ffbff65b387fdae11742d4ebf 100644 (file)
@@ -982,12 +982,13 @@ static int mx3_camera_querycap(struct soc_camera_host *ici,
        return 0;
 }
 
-static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int mx3_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
        unsigned long bus_flags, common_flags;
        u32 dw, sens_conf;
        const struct soc_mbus_pixelfmt *fmt;
@@ -1285,19 +1286,7 @@ static struct platform_driver mx3_camera_driver = {
        .remove         = __devexit_p(mx3_camera_remove),
 };
 
-
-static int __init mx3_camera_init(void)
-{
-       return platform_driver_register(&mx3_camera_driver);
-}
-
-static void __exit mx3_camera_exit(void)
-{
-       platform_driver_unregister(&mx3_camera_driver);
-}
-
-module_init(mx3_camera_init);
-module_exit(mx3_camera_exit);
+module_platform_driver(mx3_camera_driver);
 
 MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
index a378c2ce1273bcf9c32391f650003f108f6b5c80..a277f95091ef2b481b369dca5cacc30cbf04afe4 100644 (file)
@@ -524,10 +524,50 @@ static int omapvid_apply_changes(struct omap_vout_device *vout)
        return 0;
 }
 
+static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
+               unsigned int irqstatus, struct timeval timevalue)
+{
+       u32 fid;
+
+       if (vout->first_int) {
+               vout->first_int = 0;
+               goto err;
+       }
+
+       if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
+               fid = 1;
+       else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
+               fid = 0;
+       else
+               goto err;
+
+       vout->field_id ^= 1;
+       if (fid != vout->field_id) {
+               if (fid == 0)
+                       vout->field_id = fid;
+       } else if (0 == fid) {
+               if (vout->cur_frm == vout->next_frm)
+                       goto err;
+
+               vout->cur_frm->ts = timevalue;
+               vout->cur_frm->state = VIDEOBUF_DONE;
+               wake_up_interruptible(&vout->cur_frm->done);
+               vout->cur_frm = vout->next_frm;
+       } else {
+               if (list_empty(&vout->dma_queue) ||
+                               (vout->cur_frm != vout->next_frm))
+                       goto err;
+       }
+
+       return vout->field_id;
+err:
+       return 0;
+}
+
 static void omap_vout_isr(void *arg, unsigned int irqstatus)
 {
-       int ret;
-       u32 addr, fid;
+       int ret, fid, mgr_id;
+       u32 addr, irq;
        struct omap_overlay *ovl;
        struct timeval timevalue;
        struct omapvideo_info *ovid;
@@ -543,112 +583,73 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
        if (!ovl->manager || !ovl->manager->device)
                return;
 
+       mgr_id = ovl->manager->id;
        cur_display = ovl->manager->device;
 
        spin_lock(&vout->vbq_lock);
        do_gettimeofday(&timevalue);
 
-       if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) {
-               switch (cur_display->type) {
-               case OMAP_DISPLAY_TYPE_DPI:
-                       if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2)))
-                               goto vout_isr_err;
-                       break;
-               case OMAP_DISPLAY_TYPE_HDMI:
-                       if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
-                               goto vout_isr_err;
-                       break;
-               default:
-                       goto vout_isr_err;
-               }
-               if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
-                       vout->cur_frm->ts = timevalue;
-                       vout->cur_frm->state = VIDEOBUF_DONE;
-                       wake_up_interruptible(&vout->cur_frm->done);
-                       vout->cur_frm = vout->next_frm;
-               }
-               vout->first_int = 0;
-               if (list_empty(&vout->dma_queue))
+       switch (cur_display->type) {
+       case OMAP_DISPLAY_TYPE_DSI:
+       case OMAP_DISPLAY_TYPE_DPI:
+               if (mgr_id == OMAP_DSS_CHANNEL_LCD)
+                       irq = DISPC_IRQ_VSYNC;
+               else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
+                       irq = DISPC_IRQ_VSYNC2;
+               else
                        goto vout_isr_err;
 
-               vout->next_frm = list_entry(vout->dma_queue.next,
-                               struct videobuf_buffer, queue);
-               list_del(&vout->next_frm->queue);
-
-               vout->next_frm->state = VIDEOBUF_ACTIVE;
+               if (!(irqstatus & irq))
+                       goto vout_isr_err;
+               break;
+       case OMAP_DISPLAY_TYPE_VENC:
+               fid = omapvid_handle_interlace_display(vout, irqstatus,
+                               timevalue);
+               if (!fid)
+                       goto vout_isr_err;
+               break;
+       case OMAP_DISPLAY_TYPE_HDMI:
+               if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
+                       goto vout_isr_err;
+               break;
+       default:
+               goto vout_isr_err;
+       }
 
-               addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
-                       + vout->cropped_offset;
+       if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
+               vout->cur_frm->ts = timevalue;
+               vout->cur_frm->state = VIDEOBUF_DONE;
+               wake_up_interruptible(&vout->cur_frm->done);
+               vout->cur_frm = vout->next_frm;
+       }
 
-               /* First save the configuration in ovelray structure */
-               ret = omapvid_init(vout, addr);
-               if (ret)
-                       printk(KERN_ERR VOUT_NAME
-                               "failed to set overlay info\n");
-               /* Enable the pipeline and set the Go bit */
-               ret = omapvid_apply_changes(vout);
-               if (ret)
-                       printk(KERN_ERR VOUT_NAME "failed to change mode\n");
-       } else {
+       vout->first_int = 0;
+       if (list_empty(&vout->dma_queue))
+               goto vout_isr_err;
 
-               if (vout->first_int) {
-                       vout->first_int = 0;
-                       goto vout_isr_err;
-               }
-               if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
-                       fid = 1;
-               else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
-                       fid = 0;
-               else
-                       goto vout_isr_err;
+       vout->next_frm = list_entry(vout->dma_queue.next,
+                       struct videobuf_buffer, queue);
+       list_del(&vout->next_frm->queue);
 
-               vout->field_id ^= 1;
-               if (fid != vout->field_id) {
-                       if (0 == fid)
-                               vout->field_id = fid;
+       vout->next_frm->state = VIDEOBUF_ACTIVE;
 
-                       goto vout_isr_err;
-               }
-               if (0 == fid) {
-                       if (vout->cur_frm == vout->next_frm)
-                               goto vout_isr_err;
-
-                       vout->cur_frm->ts = timevalue;
-                       vout->cur_frm->state = VIDEOBUF_DONE;
-                       wake_up_interruptible(&vout->cur_frm->done);
-                       vout->cur_frm = vout->next_frm;
-               } else if (1 == fid) {
-                       if (list_empty(&vout->dma_queue) ||
-                                       (vout->cur_frm != vout->next_frm))
-                               goto vout_isr_err;
-
-                       vout->next_frm = list_entry(vout->dma_queue.next,
-                                       struct videobuf_buffer, queue);
-                       list_del(&vout->next_frm->queue);
-
-                       vout->next_frm->state = VIDEOBUF_ACTIVE;
-                       addr = (unsigned long)
-                               vout->queued_buf_addr[vout->next_frm->i] +
-                               vout->cropped_offset;
-                       /* First save the configuration in ovelray structure */
-                       ret = omapvid_init(vout, addr);
-                       if (ret)
-                               printk(KERN_ERR VOUT_NAME
-                                               "failed to set overlay info\n");
-                       /* Enable the pipeline and set the Go bit */
-                       ret = omapvid_apply_changes(vout);
-                       if (ret)
-                               printk(KERN_ERR VOUT_NAME
-                                               "failed to change mode\n");
-               }
+       addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
+               + vout->cropped_offset;
 
-       }
+       /* First save the configuration in ovelray structure */
+       ret = omapvid_init(vout, addr);
+       if (ret)
+               printk(KERN_ERR VOUT_NAME
+                       "failed to set overlay info\n");
+       /* Enable the pipeline and set the Go bit */
+       ret = omapvid_apply_changes(vout);
+       if (ret)
+               printk(KERN_ERR VOUT_NAME "failed to change mode\n");
 
 vout_isr_err:
        spin_unlock(&vout->vbq_lock);
 }
 
-
 /* Video buffer call backs */
 
 /*
@@ -664,10 +665,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
        u32 phy_addr = 0, virt_addr = 0;
        struct omap_vout_device *vout = q->priv_data;
        struct omapvideo_info *ovid = &vout->vid_info;
+       int vid_max_buf_size;
 
        if (!vout)
                return -EINVAL;
 
+       vid_max_buf_size = vout->vid == OMAP_VIDEO1 ? video1_bufsize :
+               video2_bufsize;
+
        if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
                return -EINVAL;
 
@@ -690,7 +695,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
                video1_numbuffers : video2_numbuffers;
 
        /* Check the size of the buffer */
-       if (*size > vout->buffer_size) {
+       if (*size > vid_max_buf_size) {
                v4l2_err(&vout->vid_dev->v4l2_dev,
                                "buffer allocation mismatch [%u] [%u]\n",
                                *size, vout->buffer_size);
index d793501cafcc516710f319cd5a9d64acced3da49..27a95d23b913493db67d20b90857e37f621fdd10 100644 (file)
@@ -25,7 +25,7 @@
 #define MAC_VRFB_CTXS  4
 #define MAX_VOUT_DEV   2
 #define MAX_OVLS       3
-#define MAX_DISPLAYS   3
+#define MAX_DISPLAYS   10
 #define MAX_MANAGERS   3
 
 #define QQVGA_WIDTH            160
index 6a6cf388bae446d70a043eac83cb09e2b6a0e4e8..c20f5ecd67904d634d818b734b49a8f68f5dc2a3 100644 (file)
@@ -1436,13 +1436,13 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
        return 0;
 }
 
-static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
-               __u32 pixfmt)
+static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
+       u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
        const struct soc_camera_format_xlate *xlate;
        const struct soc_mbus_pixelfmt *fmt;
        struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
@@ -1713,17 +1713,7 @@ static struct platform_driver omap1_cam_driver = {
        .remove         = __exit_p(omap1_cam_remove),
 };
 
-static int __init omap1_cam_init(void)
-{
-       return platform_driver_register(&omap1_cam_driver);
-}
-module_init(omap1_cam_init);
-
-static void __exit omap1_cam_exit(void)
-{
-       platform_driver_unregister(&omap1_cam_driver);
-}
-module_exit(omap1_cam_exit);
+module_platform_driver(omap1_cam_driver);
 
 module_param(sg_mode, bool, 0644);
 MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
index 45522e603185f45dbc5bac41c3c99032f06da6ca..7d3864144368c30e7a1916ae169c4999765fba62 100644 (file)
@@ -1868,21 +1868,7 @@ static struct platform_driver omap24xxcam_driver = {
        },
 };
 
-/*
- *
- * Module initialisation and deinitialisation
- *
- */
-
-static int __init omap24xxcam_init(void)
-{
-       return platform_driver_register(&omap24xxcam_driver);
-}
-
-static void __exit omap24xxcam_cleanup(void)
-{
-       platform_driver_unregister(&omap24xxcam_driver);
-}
+module_platform_driver(omap24xxcam_driver);
 
 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
 MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver");
@@ -1894,6 +1880,3 @@ MODULE_PARM_DESC(video_nr,
 module_param(capture_mem, int, 0);
 MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture "
                 "buffers (default 4800kiB)");
-
-module_init(omap24xxcam_init);
-module_exit(omap24xxcam_cleanup);
index d4c48ef227fb9379ed34ee4d09976cd86836658b..12d5f923e1d0fbf01ff18c08ce904cea53ab3fc4 100644 (file)
@@ -403,6 +403,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
 static void isp_isr_sbl(struct isp_device *isp)
 {
        struct device *dev = isp->dev;
+       struct isp_pipeline *pipe;
        u32 sbl_pcr;
 
        /*
@@ -416,27 +417,38 @@ static void isp_isr_sbl(struct isp_device *isp)
        if (sbl_pcr)
                dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
 
-       if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
-                    | ISPSBL_PCR_CSIB_WBL_OVF)) {
-               isp->isp_ccdc.error = 1;
-               if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
-                       isp->isp_prev.error = 1;
-               if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
-                       isp->isp_res.error = 1;
+       if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
+
+       if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
+
+       if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
        }
 
        if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
-               isp->isp_prev.error = 1;
-               if (isp->isp_res.input == RESIZER_INPUT_VP &&
-                   !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
-                       isp->isp_res.error = 1;
+               pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
        }
 
        if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
                       | ISPSBL_PCR_RSZ2_WBL_OVF
                       | ISPSBL_PCR_RSZ3_WBL_OVF
-                      | ISPSBL_PCR_RSZ4_WBL_OVF))
-               isp->isp_res.error = 1;
+                      | ISPSBL_PCR_RSZ4_WBL_OVF)) {
+               pipe = to_isp_pipeline(&isp->isp_res.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
 
        if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
                omap3isp_stat_sbl_overflow(&isp->isp_af);
@@ -464,24 +476,17 @@ static irqreturn_t isp_isr(int irq, void *_isp)
                                       IRQ0STATUS_HS_VS_IRQ;
        struct isp_device *isp = _isp;
        u32 irqstatus;
-       int ret;
 
        irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
        isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
 
        isp_isr_sbl(isp);
 
-       if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
-               ret = omap3isp_csi2_isr(&isp->isp_csi2a);
-               if (ret)
-                       isp->isp_ccdc.error = 1;
-       }
+       if (irqstatus & IRQ0STATUS_CSIA_IRQ)
+               omap3isp_csi2_isr(&isp->isp_csi2a);
 
-       if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
-               ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
-               if (ret)
-                       isp->isp_ccdc.error = 1;
-       }
+       if (irqstatus & IRQ0STATUS_CSIB_IRQ)
+               omap3isp_ccp2_isr(&isp->isp_ccp2);
 
        if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
                if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
@@ -2222,24 +2227,7 @@ static struct platform_driver omap3isp_driver = {
        },
 };
 
-/*
- * isp_init - ISP module initialization.
- */
-static int __init isp_init(void)
-{
-       return platform_driver_register(&omap3isp_driver);
-}
-
-/*
- * isp_cleanup - ISP module cleanup.
- */
-static void __exit isp_cleanup(void)
-{
-       platform_driver_unregister(&omap3isp_driver);
-}
-
-module_init(isp_init);
-module_exit(isp_cleanup);
+module_platform_driver(omap3isp_driver);
 
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_DESCRIPTION("TI OMAP3 ISP driver");
index d341ba12593f0bc0a93fc1f66dc57a899b9aa1a7..a74a79701d346786fb8f3b91a7823694a6c74bdb 100644 (file)
@@ -1406,9 +1406,8 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
 
 static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
 {
-       struct isp_pipeline *pipe =
-               to_isp_pipeline(&ccdc->video_out.video.entity);
-       struct video_device *vdev = ccdc->subdev.devnode;
+       struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+       struct video_device *vdev = &ccdc->subdev.devnode;
        struct v4l2_event event;
 
        memset(&event, 0, sizeof(event));
@@ -1428,8 +1427,11 @@ static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
        unsigned long flags;
 
        if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
+               struct isp_pipeline *pipe =
+                       to_isp_pipeline(&ccdc->subdev.entity);
+
                ccdc_lsc_error_handler(ccdc);
-               ccdc->error = 1;
+               pipe->error = true;
                dev_dbg(to_device(ccdc), "lsc prefetch error\n");
        }
 
@@ -1504,7 +1506,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
                goto done;
        }
 
-       buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
+       buffer = omap3isp_video_buffer_next(&ccdc->video_out);
        if (buffer != NULL) {
                ccdc_set_outaddr(ccdc, buffer->isp_addr);
                restart = 1;
@@ -1518,7 +1520,6 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
                                        ISP_PIPELINE_STREAM_SINGLESHOT);
 
 done:
-       ccdc->error = 0;
        return restart;
 }
 
@@ -1744,7 +1745,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
                 */
                ccdc_config_vp(ccdc);
                ccdc_enable_vp(ccdc, 1);
-               ccdc->error = 0;
                ccdc_print_status(ccdc);
        }
 
index 483a19cac1ad9497ee9d1598eed3bf9f00830d45..6d0264bab75b0566c21e7939b39679a73a0a3d3a 100644 (file)
@@ -150,7 +150,6 @@ struct ispccdc_lsc {
  * @input: Active input
  * @output: Active outputs
  * @video_out: Output video node
- * @error: A hardware error occurred during capture
  * @alaw: A-law compression enabled (1) or disabled (0)
  * @lpf: Low pass filter enabled (1) or disabled (0)
  * @obclamp: Optical-black clamp enabled (1) or disabled (0)
@@ -178,7 +177,6 @@ struct isp_ccdc_device {
        enum ccdc_input_entity input;
        unsigned int output;
        struct isp_video video_out;
-       unsigned int error;
 
        unsigned int alaw:1,
                     lpf:1,
index 904ca8c8b17fb982e56faa32015336c1aea6435b..70ddbf35b223bc7f070d6572d0c1e60cbc15b74c 100644 (file)
@@ -556,7 +556,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
        struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
        struct isp_buffer *buffer;
 
-       buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
+       buffer = omap3isp_video_buffer_next(&ccp2->video_in);
        if (buffer != NULL)
                ccp2_set_inaddr(ccp2, buffer->isp_addr);
 
@@ -567,8 +567,6 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
                        omap3isp_pipeline_set_stream(pipe,
                                                ISP_PIPELINE_STREAM_SINGLESHOT);
        }
-
-       ccp2->error = 0;
 }
 
 /*
@@ -576,13 +574,11 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
  * @ccp2: Pointer to ISP CCP2 device
  *
  * This will handle the CCP2 interrupts
- *
- * Returns -EIO in case of error, or 0 on success.
  */
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
 {
+       struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
        struct isp_device *isp = to_isp_device(ccp2);
-       int ret = 0;
        static const u32 ISPCCP2_LC01_ERROR =
                ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
                ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
@@ -604,19 +600,18 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
                       ISPCCP2_LCM_IRQSTATUS);
        /* Errors */
        if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
-               ccp2->error = 1;
+               pipe->error = true;
                dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
-               return -EIO;
+               return;
        }
 
        if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
-               ccp2->error = 1;
+               pipe->error = true;
                dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
-               ret = -EIO;
        }
 
        if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
-               return 0;
+               return;
 
        /* Frame number propagation */
        if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
@@ -629,8 +624,6 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
        /* Handle queued buffers on frame end interrupts */
        if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
                ccp2_isr_buffer(ccp2);
-
-       return ret;
 }
 
 /* -----------------------------------------------------------------------------
@@ -867,7 +860,6 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
                if (enable == ISP_PIPELINE_STREAM_STOPPED)
                        return 0;
                atomic_set(&ccp2->stopping, 0);
-               ccp2->error = 0;
        }
 
        switch (enable) {
index 6674e9de2cd7aace79aedb9fbceb958fbb27bf63..76d65f4576ef017d6ca2dad854a0697e4799e35c 100644 (file)
@@ -82,7 +82,6 @@ struct isp_ccp2_device {
        struct isp_video video_in;
        struct isp_csiphy *phy;
        struct regulator *vdds_csib;
-       unsigned int error;
        enum isp_pipeline_stream_state state;
        wait_queue_head_t wait;
        atomic_t stopping;
@@ -94,6 +93,6 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp);
 int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
                        struct v4l2_device *vdev);
 void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
 
 #endif /* OMAP3_ISP_CCP2_H */
index 0c5f1cb9d99d874d3807db776357879726bf9a0e..fcb5168996a73f740b513087b441dfaa66feaf39 100644 (file)
@@ -667,7 +667,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2)
 
        csi2_ctx_enable(isp, csi2, 0, 0);
 
-       buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
+       buffer = omap3isp_video_buffer_next(&csi2->video_out);
 
        /*
         * Let video queue operation restart engine if there is an underrun
@@ -727,17 +727,15 @@ static void csi2_isr_ctx(struct isp_csi2_device *csi2,
 
 /*
  * omap3isp_csi2_isr - CSI2 interrupt handling.
- *
- * Return -EIO on Transmission error
  */
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2)
 {
+       struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
        u32 csi2_irqstatus, cpxio1_irqstatus;
        struct isp_device *isp = csi2->isp;
-       int retval = 0;
 
        if (!csi2->available)
-               return -ENODEV;
+               return;
 
        csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
        isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
@@ -750,7 +748,7 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
                               csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
                dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
                        "%x\n", cpxio1_irqstatus);
-               retval = -EIO;
+               pipe->error = true;
        }
 
        if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
@@ -775,11 +773,11 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
                         ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
                        (csi2_irqstatus &
                         ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
-               retval = -EIO;
+               pipe->error = true;
        }
 
        if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
-               return 0;
+               return;
 
        /* Successful cases */
        if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
@@ -787,8 +785,6 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
 
        if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
                dev_dbg(isp->dev, "CSI2: ECC correction done\n");
-
-       return retval;
 }
 
 /* -----------------------------------------------------------------------------
index 456fb7fb8a0f68b853153c46840f4cd2d8d94958..885ad79a767842726bb93653517a11a9dfeacea9 100644 (file)
@@ -156,7 +156,7 @@ struct isp_csi2_device {
        atomic_t stopping;
 };
 
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
 int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
 int omap3isp_csi2_init(struct isp_device *isp);
 void omap3isp_csi2_cleanup(struct isp_device *isp);
index ccb876fe023f1c1a1257d228b692305c9d6267e3..6d0fb2c8c26da01e4cc8643f749fa1aa8be4ea80 100644 (file)
@@ -116,11 +116,11 @@ static struct omap3isp_prev_csc flr_prev_csc = {
 #define PREV_MIN_IN_HEIGHT     8
 #define PREV_MAX_IN_HEIGHT     16384
 
-#define PREV_MIN_OUT_WIDTH     0
-#define PREV_MIN_OUT_HEIGHT    0
-#define PREV_MAX_OUT_WIDTH     1280
-#define PREV_MAX_OUT_WIDTH_ES2 3300
-#define PREV_MAX_OUT_WIDTH_3630        4096
+#define PREV_MIN_OUT_WIDTH             0
+#define PREV_MIN_OUT_HEIGHT            0
+#define PREV_MAX_OUT_WIDTH_REV_1       1280
+#define PREV_MAX_OUT_WIDTH_REV_2       3300
+#define PREV_MAX_OUT_WIDTH_REV_15      4096
 
 /*
  * Coeficient Tables for the submodules in Preview.
@@ -1306,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
 
        switch (isp->revision) {
        case ISP_REVISION_1_0:
-               return PREV_MAX_OUT_WIDTH;
+               return PREV_MAX_OUT_WIDTH_REV_1;
 
        case ISP_REVISION_2_0:
        default:
-               return PREV_MAX_OUT_WIDTH_ES2;
+               return PREV_MAX_OUT_WIDTH_REV_2;
 
        case ISP_REVISION_15_0:
-               return PREV_MAX_OUT_WIDTH_3630;
+               return PREV_MAX_OUT_WIDTH_REV_15;
        }
 }
 
@@ -1404,16 +1404,14 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
        int restart = 0;
 
        if (prev->input == PREVIEW_INPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&prev->video_in,
-                                                   prev->error);
+               buffer = omap3isp_video_buffer_next(&prev->video_in);
                if (buffer != NULL)
                        preview_set_inaddr(prev, buffer->isp_addr);
                pipe->state |= ISP_PIPELINE_IDLE_INPUT;
        }
 
        if (prev->output & PREVIEW_OUTPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&prev->video_out,
-                                                   prev->error);
+               buffer = omap3isp_video_buffer_next(&prev->video_out);
                if (buffer != NULL) {
                        preview_set_outaddr(prev, buffer->isp_addr);
                        restart = 1;
@@ -1440,8 +1438,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
        default:
                return;
        }
-
-       prev->error = 0;
 }
 
 /*
@@ -1565,7 +1561,6 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
                omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
                preview_configure(prev);
                atomic_set(&prev->stopping, 0);
-               prev->error = 0;
                preview_print_status(prev);
        }
 
index f54e775c2df4e2e2e9a6eba4935d34b4cff31b64..09686607973c4b7c13a340c43290228fa1173b9b 100644 (file)
@@ -157,7 +157,6 @@ struct isptables_update {
  * @output: Bitmask of the active output
  * @video_in: Input video entity
  * @video_out: Output video entity
- * @error: A hardware error occurred during capture
  * @params: Module configuration data
  * @shadow_update: If set, update the hardware configured in the next interrupt
  * @underrun: Whether the preview entity has queued buffers on the output
@@ -179,7 +178,6 @@ struct isp_prev_device {
        unsigned int output;
        struct isp_video video_in;
        struct isp_video video_out;
-       unsigned int error;
 
        struct prev_params params;
        unsigned int shadow_update:1;
index 50e593bfcfaf02d069311fe3f6543089eb0d749c..6958a9e3dc222864cf3caaa18435dd6c8901c86f 100644 (file)
@@ -1038,7 +1038,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
        /* Complete the output buffer and, if reading from memory, the input
         * buffer.
         */
-       buffer = omap3isp_video_buffer_next(&res->video_out, res->error);
+       buffer = omap3isp_video_buffer_next(&res->video_out);
        if (buffer != NULL) {
                resizer_set_outaddr(res, buffer->isp_addr);
                restart = 1;
@@ -1047,7 +1047,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
        pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
 
        if (res->input == RESIZER_INPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&res->video_in, 0);
+               buffer = omap3isp_video_buffer_next(&res->video_in);
                if (buffer != NULL)
                        resizer_set_inaddr(res, buffer->isp_addr);
                pipe->state |= ISP_PIPELINE_IDLE_INPUT;
@@ -1064,8 +1064,6 @@ static void resizer_isr_buffer(struct isp_res_device *res)
                if (restart)
                        resizer_enable_oneshot(res);
        }
-
-       res->error = 0;
 }
 
 /*
@@ -1154,7 +1152,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
 
                omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
                resizer_configure(res);
-               res->error = 0;
                resizer_print_status(res);
        }
 
index 76abc2e4212612c743d5d65c96d4b07acfe3a695..70c1c0e1bbdf687594c5ac26baa5361bd3b16a18 100644 (file)
@@ -107,7 +107,6 @@ struct isp_res_device {
        enum resizer_input_entity input;
        struct isp_video video_in;
        struct isp_video video_out;
-       unsigned int error;
 
        u32 addr_base;   /* stored source buffer address in memory mode */
        u32 crop_offset; /* additional offset for crop in memory mode */
index bd3aebafafa08c29502c5624623b3cf3c1830b74..b02070057724a47263f732ad8a05a6df56ad59ea 100644 (file)
@@ -211,14 +211,14 @@ static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
        mbus->width = pix->width;
        mbus->height = pix->height;
 
-       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+       /* Skip the last format in the loop so that it will be selected if no
+        * match is found.
+        */
+       for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
                if (formats[i].pixelformat == pix->pixelformat)
                        break;
        }
 
-       if (WARN_ON(i == ARRAY_SIZE(formats)))
-               return;
-
        mbus->code = formats[i].code;
        mbus->colorspace = pix->colorspace;
        mbus->field = pix->field;
@@ -581,21 +581,20 @@ static const struct isp_video_queue_operations isp_video_queue_ops = {
 /*
  * omap3isp_video_buffer_next - Complete the current buffer and return the next
  * @video: ISP video object
- * @error: Whether an error occurred during capture
  *
  * Remove the current video buffer from the DMA queue and fill its timestamp,
  * field count and state fields before waking up its completion handler.
  *
- * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0)
- * or VIDEOBUF_ERROR otherwise (@error is non-zero).
+ * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
+ * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
+ * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
  *
  * The DMA queue is expected to contain at least one buffer.
  *
  * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
  * empty.
  */
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
-                                             unsigned int error)
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 {
        struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
        struct isp_video_queue *queue = video->queue;
@@ -630,7 +629,13 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
        else
                buf->vbuf.sequence = atomic_read(&pipe->frame_number);
 
-       buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
+       /* Report pipeline errors to userspace on the capture device side. */
+       if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
+               buf->state = ISP_BUF_STATE_ERROR;
+               pipe->error = false;
+       } else {
+               buf->state = ISP_BUF_STATE_DONE;
+       }
 
        wake_up(&buf->wait);
 
@@ -1016,6 +1021,8 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
        if (ret < 0)
                goto error;
 
+       pipe->error = false;
+
        spin_lock_irqsave(&pipe->lock, flags);
        pipe->state &= ~ISP_PIPELINE_STREAM;
        pipe->state |= state;
index 08cbfa144e6e4f1a7beb1baa2a2dc2571a5b6d71..d91bdb919be0c8c925499a99cbdeb311fc0efb2f 100644 (file)
@@ -85,6 +85,10 @@ enum isp_pipeline_state {
        ISP_PIPELINE_STREAM = 64,
 };
 
+/*
+ * struct isp_pipeline - An ISP hardware pipeline
+ * @error: A hardware error occurred during capture
+ */
 struct isp_pipeline {
        struct media_pipeline pipe;
        spinlock_t lock;                /* Pipeline state and queue flags */
@@ -96,6 +100,7 @@ struct isp_pipeline {
        unsigned int max_rate;
        atomic_t frame_number;
        bool do_propagation; /* of frame number */
+       bool error;
        struct v4l2_fract max_timeperframe;
 };
 
@@ -194,8 +199,7 @@ void omap3isp_video_cleanup(struct isp_video *video);
 int omap3isp_video_register(struct isp_video *video,
                            struct v4l2_device *vdev);
 void omap3isp_video_unregister(struct isp_video *video);
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
-                                             unsigned int error);
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
 void omap3isp_video_resume(struct isp_video *video, int continuous);
 struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
 
index 122b45760f0d9103306502e09e08c9d0b03002ae..ebc2c7e39233c1430df417492542d6769203e301 100644 (file)
@@ -2546,8 +2546,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        }
 
        /* Define and configure additional controls from cx2341x module. */
-       hdw->mpeg_ctrl_info = kzalloc(
-               sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+       hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT,
+                                     sizeof(*(hdw->mpeg_ctrl_info)),
+                                     GFP_KERNEL);
        if (!hdw->mpeg_ctrl_info) goto fail;
        for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
                cptr = hdw->controls + idx + CTRLDEF_COUNT;
index 3977addf3ba8553d586bfb0a3b8521e146435e7e..905d41d90c6aa816b7162ddf1d0f5e99bee4912a 100644 (file)
@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
 #include "pwc-nala.h"
 };
 
-static void pwc_set_image_buffer_size(struct pwc_device *pdev);
-
 /****************************************************************************/
 
 static int _send_control_msg(struct pwc_device *pdev,
@@ -113,10 +111,9 @@ static int _send_control_msg(struct pwc_device *pdev,
        void *kbuf = NULL;
 
        if (buflen) {
-               kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
+               kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
                if (kbuf == NULL)
                        return -ENOMEM;
-               memcpy(kbuf, buf, buflen);
        }
 
        rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
@@ -171,7 +168,8 @@ int send_control_msg(struct pwc_device *pdev,
                request, value, pdev->vcinterface, buf, buflen);
 }
 
-static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
+                              int *compression)
 {
        unsigned char buf[3];
        int ret, fps;
@@ -221,10 +219,10 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
 
        /* Set various parameters */
        pdev->vframes = frames;
-       pdev->vsize = size;
        pdev->valternate = pEntry->alternate;
-       pdev->image = pwc_image_sizes[size];
-       pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
+       pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
        if (pEntry->compressed) {
                if (pdev->release < 5) { /* 4 fold compression */
                        pdev->vbandlength = 528;
@@ -237,38 +235,40 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
        }
        else
                pdev->vbandlength = 0;
+
+       /* Let pwc-if.c:isoc_init know we don't support higher compression */
+       *compression = 3;
+
        return 0;
 }
 
 
-static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
+       int *compression)
 {
        unsigned char buf[13];
        const struct Timon_table_entry *pChoose;
        int ret, fps;
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
+           *compression < 0 || *compression > 3)
                return -EINVAL;
        if (size == PSZ_VGA && frames > 15)
                return -EINVAL;
        fps = (frames / 5) - 1;
 
-       /* Find a supported framerate with progressively higher compression ratios
-          if the preferred ratio is not available.
-       */
+       /* Find a supported framerate with progressively higher compression */
        pChoose = NULL;
-       while (compression <= 3) {
-          pChoose = &Timon_table[size][fps][compression];
-          if (pChoose->alternate != 0)
-            break;
-          compression++;
+       while (*compression <= 3) {
+               pChoose = &Timon_table[size][fps][*compression];
+               if (pChoose->alternate != 0)
+                       break;
+               (*compression)++;
        }
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
        memcpy(buf, pChoose->mode, 13);
-       if (snapshot)
-               buf[0] |= 0x80;
        ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
        if (ret < 0)
                return ret;
@@ -284,55 +284,38 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
 
        /* Set various parameters */
        pdev->vframes = frames;
-       pdev->vsize = size;
-       pdev->vsnapshot = snapshot;
        pdev->valternate = pChoose->alternate;
-       pdev->image = pwc_image_sizes[size];
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
        pdev->vbandlength = pChoose->bandlength;
        if (pChoose->bandlength > 0)
-               pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+               pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
        else
-               pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
        return 0;
 }
 
 
-static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
+       int *compression)
 {
        const struct Kiara_table_entry *pChoose = NULL;
        int fps, ret;
        unsigned char buf[12];
-       struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
 
-       if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+       if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
+           *compression < 0 || *compression > 3)
                return -EINVAL;
        if (size == PSZ_VGA && frames > 15)
                return -EINVAL;
        fps = (frames / 5) - 1;
 
-       /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-       if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-       {
-               /* Only available in case the raw palette is selected or
-                  we have the decompressor available. This mode is
-                  only available in compressed form
-               */
-               PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
-               pChoose = &RawEntry;
-       }
-       else
-       {
-               /* Find a supported framerate with progressively higher compression ratios
-                  if the preferred ratio is not available.
-                  Skip this step when using RAW modes.
-               */
-               snapshot = 0;
-               while (compression <= 3) {
-                       pChoose = &Kiara_table[size][fps][compression];
-                       if (pChoose->alternate != 0)
-                               break;
-                       compression++;
-               }
+       /* Find a supported framerate with progressively higher compression */
+       while (*compression <= 3) {
+               pChoose = &Kiara_table[size][fps][*compression];
+               if (pChoose->alternate != 0)
+                       break;
+               (*compression)++;
        }
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
@@ -341,8 +324,6 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
 
        /* usb_control_msg won't take staticly allocated arrays as argument?? */
        memcpy(buf, pChoose->mode, 12);
-       if (snapshot)
-               buf[0] |= 0x80;
 
        /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
        ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
@@ -359,61 +340,43 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
        memcpy(pdev->cmd_buf, buf, 12);
        /* All set and go */
        pdev->vframes = frames;
-       pdev->vsize = size;
-       pdev->vsnapshot = snapshot;
        pdev->valternate = pChoose->alternate;
-       pdev->image = pwc_image_sizes[size];
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
        pdev->vbandlength = pChoose->bandlength;
        if (pdev->vbandlength > 0)
-               pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
+               pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
        else
-               pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
-       PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
-           pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
+               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+       PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
+           pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
        return 0;
 }
 
-
-
-/**
-   @pdev: device structure
-   @width: viewport width
-   @height: viewport height
-   @frame: framerate, in fps
-   @compression: preferred compression ratio
-   @snapshot: snapshot mode or streaming
- */
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+       int frames, int *compression)
 {
        int ret, size;
 
        PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
-       size = pwc_decode_size(pdev, width, height);
-       if (size < 0) {
-               PWC_DEBUG_MODULE("Could not find suitable size.\n");
-               return -ERANGE;
-       }
+       size = pwc_get_size(pdev, width, height);
        PWC_TRACE("decode_size = %d.\n", size);
 
        if (DEVICE_USE_CODEC1(pdev->type)) {
-               ret = set_video_mode_Nala(pdev, size, frames);
+               ret = set_video_mode_Nala(pdev, size, frames, compression);
 
        } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+               ret = set_video_mode_Kiara(pdev, size, frames, compression);
 
        } else {
-               ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+               ret = set_video_mode_Timon(pdev, size, frames, compression);
        }
        if (ret < 0) {
                PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
                return ret;
        }
-       pdev->view.x = width;
-       pdev->view.y = height;
-       pdev->vcompression = compression;
        pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
-       pwc_set_image_buffer_size(pdev);
-       PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+       PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
        return 0;
 }
 
@@ -470,34 +433,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
        return ret;
 }
 
-static void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-       int factor = 0;
-
-       /* for V4L2_PIX_FMT_YUV420 */
-       switch (pdev->pixfmt) {
-       case V4L2_PIX_FMT_YUV420:
-               factor = 6;
-               break;
-       case V4L2_PIX_FMT_PWC1:
-       case V4L2_PIX_FMT_PWC2:
-               factor = 6; /* can be uncompressed YUV420P */
-               break;
-       }
-
-       /* Set sizes in bytes */
-       pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-       pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-       /* Align offset, or you'll get some very weird results in
-          YUV420 mode... x must be multiple of 4 (to get the Y's in
-          place), and y even (or you'll mixup U & V). This is less of a
-          problem for YUV420P.
-        */
-       pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-       pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-}
-
 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
 {
        int ret;
@@ -598,54 +533,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
                          power ? "on" : "off", r);
 }
 
-static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
-{
-       unsigned char buf;
-
-       /* useful range is 0x01..0x20 */
-       buf = speed / 0x7f0;
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
-}
-
-static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *value = buf * 0x7f0;
-       return 0;
-}
-
-
-static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
-{
-       unsigned char buf;
-
-       /* useful range is 0x01..0x3F */
-       buf = (delay >> 10);
-       return send_control_msg(pdev,
-               SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
-}
-
-static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
-{
-       unsigned char buf;
-       int ret;
-
-       ret = recv_control_msg(pdev,
-               GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *value = buf << 10;
-       return 0;
-}
-
-
 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
        unsigned char buf[2];
@@ -675,108 +562,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
        return r;
 }
 
-static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
-{
-       unsigned char buf[2];
-       int ret;
-
-       if (pdev->type < 730) {
-               *on_value = -1;
-               *off_value = -1;
-               return 0;
-       }
-
-       ret = recv_control_msg(pdev,
-               GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       *on_value = buf[0] * 100;
-       *off_value = buf[1] * 100;
-       return 0;
-}
-
-static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
-{
-       unsigned char buf;
-
-       buf = flags & 0x03; // only lower two bits are currently used
-       return send_control_msg(pdev,
-               SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_mpt_reset(struct pwc_device *pdev, int flags)
-{
-       int ret;
-       ret = _pwc_mpt_reset(pdev, flags);
-       if (ret >= 0) {
-               pdev->pan_angle = 0;
-               pdev->tilt_angle = 0;
-       }
-       return ret;
-}
-
-static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
-{
-       unsigned char buf[4];
-
-       /* set new relative angle; angles are expressed in degrees * 100,
-          but cam as .5 degree resolution, hence divide by 200. Also
-          the angle must be multiplied by 64 before it's send to
-          the cam (??)
-        */
-       pan  =  64 * pan  / 100;
-       tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
-       buf[0] = pan & 0xFF;
-       buf[1] = (pan >> 8) & 0xFF;
-       buf[2] = tilt & 0xFF;
-       buf[3] = (tilt >> 8) & 0xFF;
-       return send_control_msg(pdev,
-               SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
-{
-       int ret;
-
-       /* check absolute ranges */
-       if (pan  < pdev->angle_range.pan_min  ||
-           pan  > pdev->angle_range.pan_max  ||
-           tilt < pdev->angle_range.tilt_min ||
-           tilt > pdev->angle_range.tilt_max)
-               return -ERANGE;
-
-       /* go to relative range, check again */
-       pan  -= pdev->pan_angle;
-       tilt -= pdev->tilt_angle;
-       /* angles are specified in degrees * 100, thus the limit = 36000 */
-       if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
-               return -ERANGE;
-
-       ret = _pwc_mpt_set_angle(pdev, pan, tilt);
-       if (ret >= 0) {
-               pdev->pan_angle  += pan;
-               pdev->tilt_angle += tilt;
-       }
-       if (ret == -EPIPE) /* stall -> out of range */
-               ret = -ERANGE;
-       return ret;
-}
-
-static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
-{
-       int ret;
-       unsigned char buf[5];
-
-       ret = recv_control_msg(pdev,
-               GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-       status->status = buf[0] & 0x7; // 3 bits are used for reporting
-       status->time_pan = (buf[1] << 8) + buf[2];
-       status->time_tilt = (buf[3] << 8) + buf[4];
-       return 0;
-}
-
 #ifdef CONFIG_USB_PWC_DEBUG
 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 {
@@ -801,420 +586,3 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
        return 0;
 }
 #endif
-
- /* End of Add-Ons                                    */
- /* ************************************************* */
-
-/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
-   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
-   and copy_to_user() calls. With these macros we circumvent this,
-   and let me maintain only one source file. The functionality is
-   exactly the same otherwise.
- */
-
-/* define local variable for arg */
-#define ARG_DEF(ARG_type, ARG_name)\
-       ARG_type *ARG_name = arg;
-/* copy arg to local variable */
-#define ARG_IN(ARG_name) /* nothing */
-/* argument itself (referenced) */
-#define ARGR(ARG_name) (*ARG_name)
-/* argument address */
-#define ARGA(ARG_name) ARG_name
-/* copy local variable to arg */
-#define ARG_OUT(ARG_name) /* nothing */
-
-/*
- * Our ctrls use native values, but the old custom pwc ioctl interface expects
- * values from 0 - 65535, define 2 helper functions to scale things. */
-static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl)
-{
-       return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum;
-}
-
-static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val)
-{
-       return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535);
-}
-
-long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
-{
-       long ret = 0;
-
-       switch(cmd) {
-       case VIDIOCPWCRUSER:
-               ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
-               break;
-
-       case VIDIOCPWCSUSER:
-               ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
-               break;
-
-       case VIDIOCPWCFACTORY:
-               ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
-               break;
-
-       case VIDIOCPWCSCQUAL:
-       {
-               ARG_DEF(int, qual)
-
-               if (vb2_is_streaming(&pdev->vb_queue)) {
-                       ret = -EBUSY;
-                       break;
-               }
-
-               ARG_IN(qual)
-               if (ARGR(qual) < 0 || ARGR(qual) > 3)
-                       ret = -EINVAL;
-               else
-                       ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
-               break;
-       }
-
-       case VIDIOCPWCGCQUAL:
-       {
-               ARG_DEF(int, qual)
-
-               ARGR(qual) = pdev->vcompression;
-               ARG_OUT(qual)
-               break;
-       }
-
-       case VIDIOCPWCPROBE:
-       {
-               ARG_DEF(struct pwc_probe, probe)
-
-               strcpy(ARGR(probe).name, pdev->vdev.name);
-               ARGR(probe).type = pdev->type;
-               ARG_OUT(probe)
-               break;
-       }
-
-       case VIDIOCPWCGSERIAL:
-       {
-               ARG_DEF(struct pwc_serial, serial)
-
-               strcpy(ARGR(serial).serial, pdev->serial);
-               ARG_OUT(serial)
-               break;
-       }
-
-       case VIDIOCPWCSAGC:
-       {
-               ARG_DEF(int, agc)
-               ARG_IN(agc)
-               ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0);
-               if (ret == 0 && ARGR(agc) >= 0)
-                       ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc));
-               break;
-       }
-
-       case VIDIOCPWCGAGC:
-       {
-               ARG_DEF(int, agc)
-               if (v4l2_ctrl_g_ctrl(pdev->autogain))
-                       ARGR(agc) = -1;
-               else
-                       ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain);
-               ARG_OUT(agc)
-               break;
-       }
-
-       case VIDIOCPWCSSHUTTER:
-       {
-               ARG_DEF(int, shutter)
-               ARG_IN(shutter)
-               ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto,
-                                      /* Menu idx 0 = auto, idx 1 = manual */
-                                      ARGR(shutter) >= 0);
-               if (ret == 0 && ARGR(shutter) >= 0)
-                       ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter));
-               break;
-       }
-
-       case VIDIOCPWCSAWB:
-       {
-               ARG_DEF(struct pwc_whitebalance, wb)
-               ARG_IN(wb)
-               ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance,
-                                      ARGR(wb).mode);
-               if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
-                       ret = pwc_ioctl_s_ctrl(pdev->red_balance,
-                                              ARGR(wb).manual_red);
-               if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
-                       ret = pwc_ioctl_s_ctrl(pdev->blue_balance,
-                                              ARGR(wb).manual_blue);
-               break;
-       }
-
-       case VIDIOCPWCGAWB:
-       {
-               ARG_DEF(struct pwc_whitebalance, wb)
-               ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance);
-               ARGR(wb).manual_red = ARGR(wb).read_red =
-                       pwc_ioctl_g_ctrl(pdev->red_balance);
-               ARGR(wb).manual_blue = ARGR(wb).read_blue =
-                       pwc_ioctl_g_ctrl(pdev->blue_balance);
-               ARG_OUT(wb)
-               break;
-       }
-
-       case VIDIOCPWCSAWBSPEED:
-       {
-               ARG_DEF(struct pwc_wb_speed, wbs)
-
-               if (ARGR(wbs).control_speed > 0) {
-                       ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
-               }
-               if (ARGR(wbs).control_delay > 0) {
-                       ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
-               }
-               break;
-       }
-
-       case VIDIOCPWCGAWBSPEED:
-       {
-               ARG_DEF(struct pwc_wb_speed, wbs)
-
-               ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
-               if (ret < 0)
-                       break;
-               ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
-               if (ret < 0)
-                       break;
-               ARG_OUT(wbs)
-               break;
-       }
-
-       case VIDIOCPWCSLED:
-       {
-               ARG_DEF(struct pwc_leds, leds)
-
-               ARG_IN(leds)
-               ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
-               break;
-       }
-
-
-       case VIDIOCPWCGLED:
-       {
-               ARG_DEF(struct pwc_leds, leds)
-
-               ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
-               ARG_OUT(leds)
-               break;
-       }
-
-       case VIDIOCPWCSCONTOUR:
-       {
-               ARG_DEF(int, contour)
-               ARG_IN(contour)
-               ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0);
-               if (ret == 0 && ARGR(contour) >= 0)
-                       ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour));
-               break;
-       }
-
-       case VIDIOCPWCGCONTOUR:
-       {
-               ARG_DEF(int, contour)
-               if (v4l2_ctrl_g_ctrl(pdev->autocontour))
-                       ARGR(contour) = -1;
-               else
-                       ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour);
-               ARG_OUT(contour)
-               break;
-       }
-
-       case VIDIOCPWCSBACKLIGHT:
-       {
-               ARG_DEF(int, backlight)
-               ARG_IN(backlight)
-               ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight));
-               break;
-       }
-
-       case VIDIOCPWCGBACKLIGHT:
-       {
-               ARG_DEF(int, backlight)
-               ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight);
-               ARG_OUT(backlight)
-               break;
-       }
-
-       case VIDIOCPWCSFLICKER:
-       {
-               ARG_DEF(int, flicker)
-               ARG_IN(flicker)
-               ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker));
-               break;
-       }
-
-       case VIDIOCPWCGFLICKER:
-       {
-               ARG_DEF(int, flicker)
-               ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker);
-               ARG_OUT(flicker)
-               break;
-       }
-
-       case VIDIOCPWCSDYNNOISE:
-       {
-               ARG_DEF(int, dynnoise)
-               ARG_IN(dynnoise)
-               ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise));
-               break;
-       }
-
-       case VIDIOCPWCGDYNNOISE:
-       {
-               ARG_DEF(int, dynnoise)
-               ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction);
-               ARG_OUT(dynnoise);
-               break;
-       }
-
-       case VIDIOCPWCGREALSIZE:
-       {
-               ARG_DEF(struct pwc_imagesize, size)
-
-               ARGR(size).width = pdev->image.x;
-               ARGR(size).height = pdev->image.y;
-               ARG_OUT(size)
-               break;
-       }
-
-       case VIDIOCPWCMPTRESET:
-       {
-               if (pdev->features & FEATURE_MOTOR_PANTILT)
-               {
-                       ARG_DEF(int, flags)
-
-                       ARG_IN(flags)
-                       ret = pwc_mpt_reset(pdev, ARGR(flags));
-               }
-               else
-               {
-                       ret = -ENXIO;
-               }
-               break;
-       }
-
-       case VIDIOCPWCMPTGRANGE:
-       {
-               if (pdev->features & FEATURE_MOTOR_PANTILT)
-               {
-                       ARG_DEF(struct pwc_mpt_range, range)
-
-                       ARGR(range) = pdev->angle_range;
-                       ARG_OUT(range)
-               }
-               else
-               {
-                       ret = -ENXIO;
-               }
-               break;
-       }
-
-       case VIDIOCPWCMPTSANGLE:
-       {
-               int new_pan, new_tilt;
-
-               if (pdev->features & FEATURE_MOTOR_PANTILT)
-               {
-                       ARG_DEF(struct pwc_mpt_angles, angles)
-
-                       ARG_IN(angles)
-                       /* The camera can only set relative angles, so
-                          do some calculations when getting an absolute angle .
-                        */
-                       if (ARGR(angles).absolute)
-                       {
-                               new_pan  = ARGR(angles).pan;
-                               new_tilt = ARGR(angles).tilt;
-                       }
-                       else
-                       {
-                               new_pan  = pdev->pan_angle  + ARGR(angles).pan;
-                               new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
-                       }
-                       ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
-               }
-               else
-               {
-                       ret = -ENXIO;
-               }
-               break;
-       }
-
-       case VIDIOCPWCMPTGANGLE:
-       {
-
-               if (pdev->features & FEATURE_MOTOR_PANTILT)
-               {
-                       ARG_DEF(struct pwc_mpt_angles, angles)
-
-                       ARGR(angles).absolute = 1;
-                       ARGR(angles).pan  = pdev->pan_angle;
-                       ARGR(angles).tilt = pdev->tilt_angle;
-                       ARG_OUT(angles)
-               }
-               else
-               {
-                       ret = -ENXIO;
-               }
-               break;
-       }
-
-       case VIDIOCPWCMPTSTATUS:
-       {
-               if (pdev->features & FEATURE_MOTOR_PANTILT)
-               {
-                       ARG_DEF(struct pwc_mpt_status, status)
-
-                       ret = pwc_mpt_get_status(pdev, ARGA(status));
-                       ARG_OUT(status)
-               }
-               else
-               {
-                       ret = -ENXIO;
-               }
-               break;
-       }
-
-       case VIDIOCPWCGVIDCMD:
-       {
-               ARG_DEF(struct pwc_video_command, vcmd);
-
-               ARGR(vcmd).type = pdev->type;
-               ARGR(vcmd).release = pdev->release;
-               ARGR(vcmd).command_len = pdev->cmd_len;
-               memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
-               ARGR(vcmd).bandlength = pdev->vbandlength;
-               ARGR(vcmd).frame_size = pdev->frame_size;
-               ARG_OUT(vcmd)
-               break;
-       }
-       /*
-       case VIDIOCPWCGVIDTABLE:
-       {
-               ARG_DEF(struct pwc_table_init_buffer, table);
-               ARGR(table).len = pdev->cmd_len;
-               memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
-               ARG_OUT(table)
-               break;
-       }
-       */
-
-       default:
-               ret = -ENOIOCTLCMD;
-               break;
-       }
-
-       if (ret > 0)
-               return 0;
-       return ret;
-}
-
-
-/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 06a4e877ba40dea4d6b69e1050a7c3a364652376..2c6709112b2f2c4d206e40701505658c73483a38 100644 (file)
@@ -27,7 +27,6 @@
 #include "pwc-timon.h"
 #include "pwc-kiara.h"
 #include "pwc-dec23.h"
-#include <media/pwc-ioctl.h>
 
 #include <linux/string.h>
 #include <linux/slab.h>
 # define USE_LOOKUP_TABLE_TO_CLAMP 1
 #endif
 
-/*
- * ENABLE_BAYER_DECODER
- *   0: bayer decoder is not build (save some space)
- *   1: bayer decoder is build and can be used
- */
-#define ENABLE_BAYER_DECODER 0
-
 static void build_subblock_pattern(struct pwc_dec23_private *pdec)
 {
        static const unsigned int initial_values[12] = {
@@ -315,6 +307,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
        }
        pdec = pwc->decompress_data;
 
+       mutex_init(&pdec->lock);
+
        if (DEVICE_USE_CODEC3(type)) {
                flags = cmd[2] & 0x18;
                if (flags == 8)
@@ -467,123 +461,6 @@ static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned i
 #endif
 }
 
-#if ENABLE_BAYER_DECODER
-/*
- * Format: 8x2 pixels
- *   . G . G . G . G . G . G . G
- *   . . . . . . . . . . . . . .
- *   . G . G . G . G . G . G . G
- *   . . . . . . . . . . . . . .
- *   or
- *   . . . . . . . . . . . . . .
- *   G . G . G . G . G . G . G .
- *   . . . . . . . . . . . . . .
- *   G . G . G . G . G . G . G .
-*/
-static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
-       /* Unroll all loops */
-       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
-       unsigned char *d = dst;
-       const int *c = src;
-
-       d[0] = cm[c[0] >> scalebits];
-       d[2] = cm[c[1] >> scalebits];
-       d[4] = cm[c[2] >> scalebits];
-       d[6] = cm[c[3] >> scalebits];
-       d[8] = cm[c[4] >> scalebits];
-       d[10] = cm[c[5] >> scalebits];
-       d[12] = cm[c[6] >> scalebits];
-       d[14] = cm[c[7] >> scalebits];
-
-       d = dst + bytes_per_line;
-       d[0] = cm[c[8] >> scalebits];
-       d[2] = cm[c[9] >> scalebits];
-       d[4] = cm[c[10] >> scalebits];
-       d[6] = cm[c[11] >> scalebits];
-       d[8] = cm[c[12] >> scalebits];
-       d[10] = cm[c[13] >> scalebits];
-       d[12] = cm[c[14] >> scalebits];
-       d[14] = cm[c[15] >> scalebits];
-#else
-       int i;
-       unsigned char *d;
-       const int *c = src;
-
-       d = dst;
-       for (i = 0; i < 8; i++, c++)
-               d[i*2] = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line;
-       for (i = 0; i < 8; i++, c++)
-               d[i*2] = CLAMP((*c) >> scalebits);
-#endif
-}
-#endif
-
-#if ENABLE_BAYER_DECODER
-/*
- * Format: 4x4 pixels
- *   R . R . R . R
- *   . B . B . B .
- *   R . R . R . R
- *   . B . B . B .
- */
-static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
-       /* Unroll all loops */
-       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
-       unsigned char *d = dst;
-       const int *c = src;
-
-       d[0] = cm[c[0] >> scalebits];
-       d[2] = cm[c[1] >> scalebits];
-       d[4] = cm[c[2] >> scalebits];
-       d[6] = cm[c[3] >> scalebits];
-
-       d = dst + bytes_per_line;
-       d[1] = cm[c[4] >> scalebits];
-       d[3] = cm[c[5] >> scalebits];
-       d[5] = cm[c[6] >> scalebits];
-       d[7] = cm[c[7] >> scalebits];
-
-       d = dst + bytes_per_line*2;
-       d[0] = cm[c[8] >> scalebits];
-       d[2] = cm[c[9] >> scalebits];
-       d[4] = cm[c[10] >> scalebits];
-       d[6] = cm[c[11] >> scalebits];
-
-       d = dst + bytes_per_line*3;
-       d[1] = cm[c[12] >> scalebits];
-       d[3] = cm[c[13] >> scalebits];
-       d[5] = cm[c[14] >> scalebits];
-       d[7] = cm[c[15] >> scalebits];
-#else
-       int i;
-       unsigned char *d;
-       const int *c = src;
-
-       d = dst;
-       for (i = 0; i < 4; i++, c++)
-               d[i*2] = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line;
-       for (i = 0; i < 4; i++, c++)
-               d[i*2+1] = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line*2;
-       for (i = 0; i < 4; i++, c++)
-               d[i*2] = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line*3;
-       for (i = 0; i < 4; i++, c++)
-               d[i*2+1] = CLAMP((*c) >> scalebits);
-#endif
-}
-#endif
-
 /*
  * To manage the stream, we keep bits in a 32 bits register.
  * fill_nbits(n): fill the reservoir with at least n bits
@@ -775,146 +652,45 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
 
 }
 
-#if ENABLE_BAYER_DECODER
-/*
- * Size need to be a multiple of 8 in width
- *
- * Return a block of four line encoded like this:
- *
- *   G R G R G R G R G R G R G R G R
- *   B G B G B G B G B G B G B G B G
- *   G R G R G R G R G R G R G R G R
- *   B G B G B G B G B G B G B G B G
- *
- */
-static void DecompressBandBayer(struct pwc_dec23_private *pdec,
-                               const unsigned char *rawyuv,
-                               unsigned char *rgbbayer,
-                               unsigned int   compressed_image_width,
-                               unsigned int   real_image_width)
-{
-       int compression_index, nblocks;
-       const unsigned char *ptable0004;
-       const unsigned char *ptable8004;
-       unsigned char *dest;
-
-       pdec->reservoir = 0;
-       pdec->nbits_in_reservoir = 0;
-       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
-
-       get_nbits(pdec, 4, compression_index);
-
-       /* pass 1: uncompress RB component */
-       nblocks = compressed_image_width / 4;
-
-       ptable0004 = pdec->table_0004_pass1[compression_index];
-       ptable8004 = pdec->table_8004_pass1[compression_index];
-       dest = rgbbayer;
-
-       /* Each block decode a square of 4x4 */
-       while (nblocks) {
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
-               dest += 8;
-               nblocks--;
-       }
-
-       /* pass 2: uncompress G component */
-       nblocks = compressed_image_width / 8;
-
-       ptable0004 = pdec->table_0004_pass2[compression_index];
-       ptable8004 = pdec->table_8004_pass2[compression_index];
-
-       /* Each block decode a square of 4x4 */
-       while (nblocks) {
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
-
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
-
-               rgbbayer += 16;
-               nblocks -= 2;
-       }
-}
-#endif
-
-
 /**
  *
  * Uncompress a pwc23 buffer.
  *
- * pwc.view: size of the image wanted
- * pwc.image: size of the image returned by the camera
- * pwc.offset: (x,y) to displayer image in the view
- *
  * src: raw data
  * dst: image output
- * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
  */
 void pwc_dec23_decompress(const struct pwc_device *pwc,
                          const void *src,
-                         void *dst,
-                         int flags)
+                         void *dst)
 {
-       int bandlines_left, stride, bytes_per_block;
-
-       bandlines_left = pwc->image.y / 4;
-       bytes_per_block = pwc->view.x * 4;
-
-       if (flags & PWCX_FLAG_BAYER) {
-#if ENABLE_BAYER_DECODER
-               /* RGB Bayer format */
-               unsigned char *rgbout;
-
-               stride = pwc->view.x * pwc->offset.y;
-               rgbout = dst + stride + pwc->offset.x;
-
-
-               while (bandlines_left--) {
-
-                       DecompressBandBayer(pwc->decompress_data,
-                                           src,
-                                           rgbout,
-                                           pwc->image.x, pwc->view.x);
-
-                       src += pwc->vbandlength;
-                       rgbout += bytes_per_block;
-
-               }
-#else
-               memset(dst, 0, pwc->view.x * pwc->view.y);
-#endif
-
-       } else {
-               /* YUV420P image format */
-               unsigned char *pout_planar_y;
-               unsigned char *pout_planar_u;
-               unsigned char *pout_planar_v;
-               unsigned int   plane_size;
-
-               plane_size = pwc->view.x * pwc->view.y;
-
-               /* offset in Y plane */
-               stride = pwc->view.x * pwc->offset.y;
-               pout_planar_y = dst + stride + pwc->offset.x;
-
-               /* offsets in U/V planes */
-               stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
-               pout_planar_u = dst + plane_size + stride;
-               pout_planar_v = dst + plane_size + plane_size / 4 + stride;
-
-               while (bandlines_left--) {
-
-                       DecompressBand23(pwc->decompress_data,
-                                        src,
-                                        pout_planar_y, pout_planar_u, pout_planar_v,
-                                        pwc->image.x, pwc->view.x);
-                       src += pwc->vbandlength;
-                       pout_planar_y += bytes_per_block;
-                       pout_planar_u += pwc->view.x;
-                       pout_planar_v += pwc->view.x;
-
-               }
+       int bandlines_left, bytes_per_block;
+       struct pwc_dec23_private *pdec = pwc->decompress_data;
+
+       /* YUV420P image format */
+       unsigned char *pout_planar_y;
+       unsigned char *pout_planar_u;
+       unsigned char *pout_planar_v;
+       unsigned int   plane_size;
+
+       mutex_lock(&pdec->lock);
+
+       bandlines_left = pwc->height / 4;
+       bytes_per_block = pwc->width * 4;
+       plane_size = pwc->height * pwc->width;
+
+       pout_planar_y = dst;
+       pout_planar_u = dst + plane_size;
+       pout_planar_v = dst + plane_size + plane_size / 4;
+
+       while (bandlines_left--) {
+               DecompressBand23(pwc->decompress_data,
+                                src,
+                                pout_planar_y, pout_planar_u, pout_planar_v,
+                                pwc->width, pwc->width);
+               src += pwc->vbandlength;
+               pout_planar_y += bytes_per_block;
+               pout_planar_u += pwc->width;
+               pout_planar_v += pwc->width;
        }
+       mutex_unlock(&pdec->lock);
 }
index a0ac4f3dff81b6960a64c2158244f08d220eb1f8..d64a3c281af6aa0d5fe03471c5cd03d16f010588 100644 (file)
@@ -29,6 +29,8 @@
 
 struct pwc_dec23_private
 {
+       struct mutex lock;
+
   unsigned int scalebits;
   unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
 
@@ -52,6 +54,5 @@ struct pwc_dec23_private
 int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
 void pwc_dec23_decompress(const struct pwc_device *pwc,
                          const void *src,
-                         void *dst,
-                         int flags);
+                         void *dst);
 #endif
index 01ff643e682dd8a7c9c20a79c980d8509b4b90a1..943d37ad0d33dd3983318bbddd0f4d19f185f55b 100644 (file)
@@ -134,7 +134,6 @@ static int default_fps = 10;
 #endif
 static int power_save = -1;
 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;
        char serial_number[30];
@@ -144,17 +143,15 @@ static struct {
 
 /***/
 
-static int pwc_video_open(struct file *file);
 static int pwc_video_close(struct file *file);
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-static void pwc_video_release(struct video_device *vfd);
 
 static const struct v4l2_file_operations pwc_fops = {
        .owner =        THIS_MODULE,
-       .open =         pwc_video_open,
+       .open =         v4l2_fh_open,
        .release =      pwc_video_close,
        .read =         pwc_video_read,
        .poll =         pwc_video_poll,
@@ -163,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = {
 };
 static struct video_device pwc_template = {
        .name =         "Philips Webcam",       /* Filled in later */
-       .release =      pwc_video_release,
+       .release =      video_device_release_empty,
        .fops =         &pwc_fops,
        .ioctl_ops =    &pwc_ioctl_ops,
 };
@@ -191,7 +188,6 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down)
 {
        if (down) {
                PWC_TRACE("Snapshot button pressed.\n");
-               pdev->snapshot_button_status = 1;
        } else {
                PWC_TRACE("Snapshot button released.\n");
        }
@@ -375,6 +371,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        int i, j, ret;
        struct usb_interface *intf;
        struct usb_host_interface *idesc = NULL;
+       int compression = 0; /* 0..3 = uncompressed..high */
 
        if (pdev->iso_init)
                return 0;
@@ -386,6 +383,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        pdev->visoc_errors = 0;
        udev = pdev->udev;
 
+retry:
+       /* We first try with low compression and then retry with a higher
+          compression setting if there is not enough bandwidth. */
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
+                                pdev->vframes, &compression);
+
        /* Get the current alternate interface, adjust packet size */
        intf = usb_ifnum_to_if(udev, 0);
        if (intf)
@@ -408,9 +411,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        }
 
        /* Set alternate interface */
-       ret = 0;
        PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
        ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+       if (ret == -ENOSPC && compression < 3) {
+               compression++;
+               goto retry;
+       }
        if (ret < 0)
                return ret;
 
@@ -454,6 +460,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        /* link */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
                ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
+               if (ret == -ENOSPC && compression < 3) {
+                       compression++;
+                       pdev->iso_init = 1;
+                       pwc_isoc_cleanup(pdev);
+                       goto retry;
+               }
                if (ret) {
                        PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
                        pdev->iso_init = 1;
@@ -517,12 +529,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
        PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
 }
 
-/*
- * Release all queued buffers, no need to take queued_bufs_lock, since all
- * iso urbs have been killed when we're called so pwc_isoc_handler won't run.
- */
 static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
 {
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
        while (!list_empty(&pdev->queued_bufs)) {
                struct pwc_frame_buf *buf;
 
@@ -531,84 +542,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
                list_del(&buf->list);
                vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
        }
-}
-
-/*********
- * sysfs
- *********/
-static struct pwc_device *cd_to_pwc(struct device *cd)
-{
-       struct video_device *vdev = to_video_device(cd);
-       return video_get_drvdata(vdev);
-}
-
-static ssize_t show_pan_tilt(struct device *class_dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct pwc_device *pdev = cd_to_pwc(class_dev);
-       return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
-}
-
-static ssize_t store_pan_tilt(struct device *class_dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct pwc_device *pdev = cd_to_pwc(class_dev);
-       int pan, tilt;
-       int ret = -EINVAL;
-
-       if (strncmp(buf, "reset", 5) == 0)
-               ret = pwc_mpt_reset(pdev, 0x3);
-
-       else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
-               ret = pwc_mpt_set_angle(pdev, pan, tilt);
-
-       if (ret < 0)
-               return ret;
-       return strlen(buf);
-}
-static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
-                  store_pan_tilt);
-
-static ssize_t show_snapshot_button_status(struct device *class_dev,
-                                          struct device_attribute *attr, char *buf)
-{
-       struct pwc_device *pdev = cd_to_pwc(class_dev);
-       int status = pdev->snapshot_button_status;
-       pdev->snapshot_button_status = 0;
-       return sprintf(buf, "%d\n", status);
-}
-
-static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
-                  NULL);
-
-static int pwc_create_sysfs_files(struct pwc_device *pdev)
-{
-       int rc;
-
-       rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
-       if (rc)
-               goto err;
-       if (pdev->features & FEATURE_MOTOR_PANTILT) {
-               rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
-               if (rc)
-                       goto err_button;
-       }
-
-       return 0;
-
-err_button:
-       device_remove_file(&pdev->vdev.dev, &dev_attr_button);
-err:
-       PWC_ERROR("Could not create sysfs files.\n");
-       return rc;
-}
-
-static void pwc_remove_sysfs_files(struct pwc_device *pdev)
-{
-       if (pdev->features & FEATURE_MOTOR_PANTILT)
-               device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
-       device_remove_file(&pdev->vdev.dev, &dev_attr_button);
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
 }
 
 #ifdef CONFIG_USB_PWC_DEBUG
@@ -644,25 +578,25 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
 /***************************************************************************/
 /* Video4Linux functions */
 
-static int pwc_video_open(struct file *file)
+int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct pwc_device *pdev;
-
-       PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
+       int r = 0;
 
-       pdev = video_get_drvdata(vdev);
-       if (!pdev->udev)
-               return -ENODEV;
-
-       file->private_data = vdev;
-       PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
-       return 0;
+       mutex_lock(&pdev->capt_file_lock);
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file) {
+               r = -EBUSY;
+               goto leave;
+       }
+       pdev->capt_file = file;
+leave:
+       mutex_unlock(&pdev->capt_file_lock);
+       return r;
 }
 
-static void pwc_video_release(struct video_device *vfd)
+static void pwc_video_release(struct v4l2_device *v)
 {
-       struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
+       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
        int hint;
 
        /* search device_hint[] table if we occupy a slot, by any chance */
@@ -685,44 +619,33 @@ static void pwc_video_release(struct video_device *vfd)
 
 static int pwc_video_close(struct file *file)
 {
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-
-       PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
+       struct pwc_device *pdev = video_drvdata(file);
 
-       pdev = video_get_drvdata(vdev);
        if (pdev->capt_file == file) {
                vb2_queue_release(&pdev->vb_queue);
                pdev->capt_file = NULL;
        }
-
-       PWC_DEBUG_OPEN("<< video_close()\n");
-       return 0;
+       return v4l2_fh_release(file);
 }
 
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
                              size_t count, loff_t *ppos)
 {
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev = video_get_drvdata(vdev);
+       struct pwc_device *pdev = video_drvdata(file);
 
        if (!pdev->udev)
                return -ENODEV;
 
-       if (pdev->capt_file != NULL &&
-           pdev->capt_file != file)
+       if (pwc_test_n_set_capt_file(pdev, file))
                return -EBUSY;
 
-       pdev->capt_file = file;
-
        return vb2_read(&pdev->vb_queue, buf, count, ppos,
                        file->f_flags & O_NONBLOCK);
 }
 
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
 {
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev = video_get_drvdata(vdev);
+       struct pwc_device *pdev = video_drvdata(file);
 
        if (!pdev->udev)
                return POLL_ERR;
@@ -732,8 +655,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
 
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev = video_get_drvdata(vdev);
+       struct pwc_device *pdev = video_drvdata(file);
 
        if (pdev->capt_file != file)
                return -EBUSY;
@@ -749,6 +671,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
        struct pwc_device *pdev = vb2_get_drv_priv(vq);
+       int size;
 
        if (*nbuffers < MIN_FRAMES)
                *nbuffers = MIN_FRAMES;
@@ -757,7 +680,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 
        *nplanes = 1;
 
-       sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
+       size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
+       sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
+                             pwc_image_sizes[size][1] * 3 / 2);
 
        return 0;
 }
@@ -812,56 +737,59 @@ static void buffer_queue(struct vb2_buffer *vb)
        unsigned long flags = 0;
 
        spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
-       list_add_tail(&buf->list, &pdev->queued_bufs);
+       /* Check the device has not disconnected between prep and queuing */
+       if (pdev->udev)
+               list_add_tail(&buf->list, &pdev->queued_bufs);
+       else
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
        spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
 }
 
 static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
        struct pwc_device *pdev = vb2_get_drv_priv(vq);
+       int r;
 
-       if (!pdev->udev)
-               return -ENODEV;
+       mutex_lock(&pdev->udevlock);
+       if (!pdev->udev) {
+               r = -ENODEV;
+               goto leave;
+       }
 
        /* Turn on camera and set LEDS on */
        pwc_camera_power(pdev, 1);
-       if (pdev->power_save) {
-               /* Restore video mode */
-               pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
-                                  pdev->vframes, pdev->vcompression,
-                                  pdev->vsnapshot);
-       }
        pwc_set_leds(pdev, led_on, led_off);
 
-       return pwc_isoc_init(pdev);
+       r = pwc_isoc_init(pdev);
+       if (r) {
+               /* If we failed turn camera and LEDS back off */
+               pwc_set_leds(pdev, 0, 0);
+               pwc_camera_power(pdev, 0);
+               /* And cleanup any queued bufs!! */
+               pwc_cleanup_queued_bufs(pdev);
+       }
+leave:
+       mutex_unlock(&pdev->udevlock);
+       return r;
 }
 
 static int stop_streaming(struct vb2_queue *vq)
 {
        struct pwc_device *pdev = vb2_get_drv_priv(vq);
 
+       mutex_lock(&pdev->udevlock);
        if (pdev->udev) {
                pwc_set_leds(pdev, 0, 0);
                pwc_camera_power(pdev, 0);
                pwc_isoc_cleanup(pdev);
        }
+       mutex_unlock(&pdev->udevlock);
+
        pwc_cleanup_queued_bufs(pdev);
 
        return 0;
 }
 
-static void pwc_lock(struct vb2_queue *vq)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vq);
-       mutex_lock(&pdev->modlock);
-}
-
-static void pwc_unlock(struct vb2_queue *vq)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vq);
-       mutex_unlock(&pdev->modlock);
-}
-
 static struct vb2_ops pwc_vb_queue_ops = {
        .queue_setup            = queue_setup,
        .buf_init               = buffer_init,
@@ -871,8 +799,6 @@ static struct vb2_ops pwc_vb_queue_ops = {
        .buf_queue              = buffer_queue,
        .start_streaming        = start_streaming,
        .stop_streaming         = stop_streaming,
-       .wait_prepare           = pwc_unlock,
-       .wait_finish            = pwc_lock,
 };
 
 /***************************************************************************/
@@ -889,6 +815,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        int vendor_id, product_id, type_id;
        int hint, rc;
        int features = 0;
+       int compression = 0;
        int video_nr = -1; /* default: use next available device */
        int my_power_save = power_save;
        char serial_number[30], *name;
@@ -1150,27 +1077,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        }
        pdev->type = type_id;
        pdev->vframes = default_fps;
-       strcpy(pdev->serial, serial_number);
        pdev->features = features;
-       if (vendor_id == 0x046D && product_id == 0x08B5) {
-               /* Logitech QuickCam Orbit
-                  The ranges have been determined experimentally; they may differ from cam to cam.
-                  Also, the exact ranges left-right and up-down are different for my cam
-                 */
-               pdev->angle_range.pan_min  = -7000;
-               pdev->angle_range.pan_max  =  7000;
-               pdev->angle_range.tilt_min = -3000;
-               pdev->angle_range.tilt_max =  2500;
-       }
        pwc_construct(pdev); /* set min/max sizes correct */
 
-       mutex_init(&pdev->modlock);
+       mutex_init(&pdev->capt_file_lock);
        mutex_init(&pdev->udevlock);
        spin_lock_init(&pdev->queued_bufs_lock);
        INIT_LIST_HEAD(&pdev->queued_bufs);
 
        pdev->udev = udev;
-       pdev->vcompression = pwc_preferred_compression;
        pdev->power_save = my_power_save;
 
        /* Init videobuf2 queue structure */
@@ -1185,9 +1100,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 
        /* Init video_device structure */
        memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
-       pdev->vdev.parent = &intf->dev;
-       pdev->vdev.lock = &pdev->modlock;
        strcpy(pdev->vdev.name, name);
+       set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
        video_set_drvdata(&pdev->vdev, pdev);
 
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -1211,9 +1125,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (hint < MAX_DEV_HINTS)
                device_hint[hint].pdev = pdev;
 
-       PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
-       usb_set_intfdata(intf, pdev);
-
 #ifdef CONFIG_USB_PWC_DEBUG
        /* Query sensor type */
        if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1227,8 +1138,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pwc_set_leds(pdev, 0, 0);
 
        /* Setup intial videomode */
-       rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
-                               pdev->vframes, pdev->vcompression, 0);
+       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
+                               &compression);
        if (rc)
                goto err_free_mem;
 
@@ -1239,20 +1150,25 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                goto err_free_mem;
        }
 
-       pdev->vdev.ctrl_handler = &pdev->ctrl_handler;
-
        /* And powerdown the camera until streaming starts */
        pwc_camera_power(pdev, 0);
 
+       /* Register the v4l2_device structure */
+       pdev->v4l2_dev.release = pwc_video_release;
+       rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
+       if (rc) {
+               PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
+               goto err_free_controls;
+       }
+
+       pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+       pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+
        rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
        if (rc < 0) {
                PWC_ERROR("Failed to register as video device (%d).\n", rc);
-               goto err_free_controls;
+               goto err_unregister_v4l2_dev;
        }
-       rc = pwc_create_sysfs_files(pdev);
-       if (rc)
-               goto err_video_unreg;
-
        PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
 
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
@@ -1261,7 +1177,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (!pdev->button_dev) {
                PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
                rc = -ENOMEM;
-               pwc_remove_sysfs_files(pdev);
                goto err_video_unreg;
        }
 
@@ -1279,7 +1194,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (rc) {
                input_free_device(pdev->button_dev);
                pdev->button_dev = NULL;
-               pwc_remove_sysfs_files(pdev);
                goto err_video_unreg;
        }
 #endif
@@ -1287,13 +1201,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        return 0;
 
 err_video_unreg:
-       if (hint < MAX_DEV_HINTS)
-               device_hint[hint].pdev = NULL;
        video_unregister_device(&pdev->vdev);
+err_unregister_v4l2_dev:
+       v4l2_device_unregister(&pdev->v4l2_dev);
 err_free_controls:
        v4l2_ctrl_handler_free(&pdev->ctrl_handler);
 err_free_mem:
-       usb_set_intfdata(intf, NULL);
+       if (hint < MAX_DEV_HINTS)
+               device_hint[hint].pdev = NULL;
        kfree(pdev);
        return rc;
 }
@@ -1301,27 +1216,26 @@ err_free_mem:
 /* The user yanked out the cable... */
 static void usb_pwc_disconnect(struct usb_interface *intf)
 {
-       struct pwc_device *pdev  = usb_get_intfdata(intf);
+       struct v4l2_device *v = usb_get_intfdata(intf);
+       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
 
        mutex_lock(&pdev->udevlock);
-       mutex_lock(&pdev->modlock);
-
-       usb_set_intfdata(intf, NULL);
        /* No need to keep the urbs around after disconnection */
        pwc_isoc_cleanup(pdev);
-       pwc_cleanup_queued_bufs(pdev);
        pdev->udev = NULL;
-
-       mutex_unlock(&pdev->modlock);
        mutex_unlock(&pdev->udevlock);
 
-       pwc_remove_sysfs_files(pdev);
+       pwc_cleanup_queued_bufs(pdev);
+
        video_unregister_device(&pdev->vdev);
+       v4l2_device_unregister(&pdev->v4l2_dev);
 
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
        if (pdev->button_dev)
                input_unregister_device(pdev->button_dev);
 #endif
+
+       v4l2_device_put(&pdev->v4l2_dev);
 }
 
 
@@ -1330,7 +1244,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
  */
 
 static int fps;
-static int compression = -1;
 static int leds[2] = { -1, -1 };
 static unsigned int leds_nargs;
 static char *dev_hint[MAX_DEV_HINTS];
@@ -1341,7 +1254,6 @@ module_param(fps, int, 0444);
 module_param_named(trace, pwc_trace, int, 0644);
 #endif
 module_param(power_save, int, 0644);
-module_param(compression, int, 0444);
 module_param_array(leds, int, &leds_nargs, 0444);
 module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
 
@@ -1350,7 +1262,6 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang
 MODULE_PARM_DESC(trace, "For debugging purposes");
 #endif
 MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
-MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
 MODULE_PARM_DESC(dev_hint, "Device node hints");
 
@@ -1384,14 +1295,6 @@ static int __init usb_pwc_init(void)
                PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
        }
 
-       if (compression >= 0) {
-               if (compression > 3) {
-                       PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
-                       return -EINVAL;
-               }
-               pwc_preferred_compression = compression;
-               PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
-       }
        if (leds[0] >= 0)
                led_on = leds[0];
        if (leds[1] >= 0)
index 047dad8c15f7ca5b88c15e3cdb51d3d79703361d..8e02b7ac21391e2d5bfd5694d6e56ede70815604 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef PWC_KIARA_H
 #define PWC_KIARA_H
 
-#include <media/pwc-ioctl.h>
+#include "pwc.h"
 
 #define PWC_FPS_MAX_KIARA 6
 
index 0b031336eab84aa1272c0a299360c739eee5e950..23a55b5814fc494ea2f2c95e8fb37b4142769726 100644 (file)
 
 #include "pwc.h"
 
-const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+const int pwc_image_sizes[PSZ_MAX][2] =
 {
-       { 128,  96, 0 }, /* sqcif */
-       { 160, 120, 0 }, /* qsif */
-       { 176, 144, 0 }, /* qcif */
-       { 320, 240, 0 }, /* sif */
-       { 352, 288, 0 }, /* cif */
-       { 640, 480, 0 }, /* vga */
+       { 128,  96 }, /* sqcif */
+       { 160, 120 }, /* qsif */
+       { 176, 144 }, /* qcif */
+       { 320, 240 }, /* sif */
+       { 352, 288 }, /* cif */
+       { 640, 480 }, /* vga */
 };
 
 /* x,y -> PSZ_ */
-int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+int pwc_get_size(struct pwc_device *pdev, int width, int height)
 {
-       int i, find;
-
-       /* Make sure we don't go beyond our max size.
-          NB: we have different limits for RAW and normal modes. In case
-          you don't have the decompressor loaded or use RAW mode,
-          the maximum viewable size is smaller.
-       */
-       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-       {
-               if (width > pdev->abs_max.x || height > pdev->abs_max.y)
-               {
-                       PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
-                       return -1;
-               }
-       }
-       else
-       {
-               if (width > pdev->view_max.x || height > pdev->view_max.y)
-               {
-                       PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
-                       return -1;
-               }
-       }
+       int i;
 
        /* Find the largest size supported by the camera that fits into the
-          requested size.
-        */
-       find = -1;
+          requested size. */
+       for (i = PSZ_MAX - 1; i >= 0; i--) {
+               if (!(pdev->image_mask & (1 << i)))
+                       continue;
+
+               if (pwc_image_sizes[i][0] <= width &&
+                   pwc_image_sizes[i][1] <= height)
+                       return i;
+       }
+
+       /* No mode found, return the smallest mode we have */
        for (i = 0; i < PSZ_MAX; i++) {
-               if (pdev->image_mask & (1 << i)) {
-                       if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
-                               find = i;
-               }
+               if (pdev->image_mask & (1 << i))
+                       return i;
        }
-       return find;
+
+       /* Never reached there always is atleast one supported mode */
+       return 0;
 }
 
-/* initialize variables depending on type and decompressor*/
+/* initialize variables depending on type and decompressor */
 void pwc_construct(struct pwc_device *pdev)
 {
        if (DEVICE_USE_CODEC1(pdev->type)) {
 
-               pdev->view_min.x = 128;
-               pdev->view_min.y =  96;
-               pdev->view_max.x = 352;
-               pdev->view_max.y = 288;
-               pdev->abs_max.x  = 352;
-               pdev->abs_max.y  = 288;
                pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
                pdev->vcinterface = 2;
                pdev->vendpoint = 4;
@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev)
 
        } else if (DEVICE_USE_CODEC3(pdev->type)) {
 
-               pdev->view_min.x = 160;
-               pdev->view_min.y = 120;
-               pdev->view_max.x = 640;
-               pdev->view_max.y = 480;
                pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-               pdev->abs_max.x = 640;
-               pdev->abs_max.y = 480;
                pdev->vcinterface = 3;
                pdev->vendpoint = 5;
                pdev->frame_header_size = TOUCAM_HEADER_SIZE;
@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev)
 
        } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
 
-               pdev->view_min.x = 128;
-               pdev->view_min.y =  96;
-               /* Anthill bug #38: PWC always reports max size, even without PWCX */
-               pdev->view_max.x = 640;
-               pdev->view_max.y = 480;
                pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
-               pdev->abs_max.x = 640;
-               pdev->abs_max.y = 480;
                pdev->vcinterface = 3;
                pdev->vendpoint = 4;
                pdev->frame_header_size = 0;
                pdev->frame_trailer_size = 0;
        }
        pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
-       pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
-       pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
 }
index a6e22224c95f58206b68ae368e9c1eec8548ec7e..270c5b9010f6f11c9129e3699b73ea6d0919ef09 100644 (file)
@@ -42,7 +42,7 @@
 #ifndef PWC_TIMON_H
 #define PWC_TIMON_H
 
-#include <media/pwc-ioctl.h>
+#include "pwc.h"
 
 #define PWC_FPS_MAX_TIMON 6
 
index 51265092bd312014308d9ed90e0369952963aedd..b65903fbcf0d536c4b309408e24e73a737fb66d5 100644 (file)
@@ -35,7 +35,7 @@
 
 int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
 {
-       int n, line, col, stride;
+       int n, line, col;
        void *yuv, *image;
        u16 *src;
        u16 *dsty, *dstu, *dstv;
@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
                return 0;
        }
 
-       vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size);
+       vb2_set_plane_payload(&fbuf->vb, 0,
+                             pdev->width * pdev->height * 3 / 2);
 
        if (pdev->vbandlength == 0) {
                /* Uncompressed mode.
-                * We copy the data into the output buffer, using the viewport
-                * size (which may be larger than the image size).
-                * Unfortunately we have to do a bit of byte stuffing to get
-                * the desired output format/size.
                 *
                 * We do some byte shuffling here to go from the
                 * native format to YUV420P.
                 */
                src = (u16 *)yuv;
-               n = pdev->view.x * pdev->view.y;
+               n = pdev->width * pdev->height;
+               dsty = (u16 *)(image);
+               dstu = (u16 *)(image + n);
+               dstv = (u16 *)(image + n + n / 4);
 
-               /* offset in Y plane */
-               stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-               dsty = (u16 *)(image + stride);
-
-               /* offsets in U/V planes */
-               stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-               dstu = (u16 *)(image + n +         stride);
-               dstv = (u16 *)(image + n + n / 4 + stride);
-
-               /* increment after each line */
-               stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
-               for (line = 0; line < pdev->image.y; line++) {
-                       for (col = 0; col < pdev->image.x; col += 4) {
+               for (line = 0; line < pdev->height; line++) {
+                       for (col = 0; col < pdev->width; col += 4) {
                                *dsty++ = *src++;
                                *dsty++ = *src++;
                                if (line & 1)
@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
                                else
                                        *dstu++ = *src++;
                        }
-                       dsty += stride;
-                       if (line & 1)
-                               dstv += (stride >> 1);
-                       else
-                               dstu += (stride >> 1);
                }
 
                return 0;
@@ -111,12 +94,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
         * the decompressor routines will write the data in planar format
         * immediately.
         */
-       if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
-               PWC_ERROR("Mode Bayer is not supported for now\n");
-               /* flags |= PWCX_FLAG_BAYER; */
-               return -ENXIO; /* No such device or address: missing decompressor */
-       }
-
        if (DEVICE_USE_CODEC1(pdev->type)) {
 
                /* TODO & FIXME */
@@ -124,10 +101,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
                return -ENXIO; /* No such device or address: missing decompressor */
 
        } else {
-               pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR);
+               pwc_dec23_decompress(pdev, yuv, image);
        }
        return 0;
 }
-
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index a10ff6b64acf21a552ae4bd58a686d7cfb27de93..80e25842e84a218dc3dada13e96ced27e68c3b39 100644 (file)
@@ -49,6 +49,7 @@ static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
 
 enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
 enum { custom_autocontour, custom_contour, custom_noise_reduction,
+       custom_awb_speed, custom_awb_delay,
        custom_save_user, custom_restore_user, custom_restore_factory };
 
 const char * const pwc_auto_whitebal_qmenu[] = {
@@ -138,6 +139,26 @@ static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
        .name    = "Restore Factory Settings",
 };
 
+static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(awb_speed),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Auto White Balance Speed",
+       .min    = 1,
+       .max    = 32,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(awb_delay),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Auto White Balance Delay",
+       .min    = 0,
+       .max    = 63,
+       .step   = 1,
+};
+
 int pwc_init_controls(struct pwc_device *pdev)
 {
        struct v4l2_ctrl_handler *hdl;
@@ -338,6 +359,23 @@ int pwc_init_controls(struct pwc_device *pdev)
        if (pdev->restore_factory)
                pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
 
+       /* Auto White Balance speed & delay */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           AWB_CONTROL_SPEED_FORMATTER, &def);
+       if (r || def < 1 || def > 32)
+               def = 1;
+       cfg = pwc_awb_speed_cfg;
+       cfg.def = def;
+       pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           AWB_CONTROL_DELAY_FORMATTER, &def);
+       if (r || def > 63)
+               def = 0;
+       cfg = pwc_awb_delay_cfg;
+       cfg.def = def;
+       pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
        if (!(pdev->features & FEATURE_MOTOR_PANTILT))
                return hdl->error;
 
@@ -357,25 +395,16 @@ int pwc_init_controls(struct pwc_device *pdev)
        return hdl->error;
 }
 
-static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
+static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
+       int width, int height, u32 pixfmt)
 {
        memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-       f->fmt.pix.width        = pdev->view.x;
-       f->fmt.pix.height       = pdev->view.y;
+       f->fmt.pix.width        = width;
+       f->fmt.pix.height       = height;
        f->fmt.pix.field        = V4L2_FIELD_NONE;
-       if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
-               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
-               f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       } else {
-               /* vbandlength contains 4 lines ...  */
-               f->fmt.pix.bytesperline = pdev->vbandlength/4;
-               f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
-               if (DEVICE_USE_CODEC1(pdev->type))
-                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;
-               else
-                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;
-       }
+       f->fmt.pix.pixelformat  = pixfmt;
+       f->fmt.pix.bytesperline = f->fmt.pix.width;
+       f->fmt.pix.sizeimage    = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
        PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
                        "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
                        f->fmt.pix.width,
@@ -391,6 +420,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma
 /* ioctl(VIDIOC_TRY_FMT) */
 static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 {
+       int size;
+
        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
                return -EINVAL;
@@ -417,15 +448,11 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 
        }
 
-       if (f->fmt.pix.width > pdev->view_max.x)
-               f->fmt.pix.width = pdev->view_max.x;
-       else if (f->fmt.pix.width < pdev->view_min.x)
-               f->fmt.pix.width = pdev->view_min.x;
-
-       if (f->fmt.pix.height > pdev->view_max.y)
-               f->fmt.pix.height = pdev->view_max.y;
-       else if (f->fmt.pix.height < pdev->view_min.y)
-               f->fmt.pix.height = pdev->view_min.y;
+       size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
+       pwc_vidioc_fill_fmt(f,
+                           pwc_image_sizes[size][0],
+                           pwc_image_sizes[size][1],
+                           f->fmt.pix.pixelformat);
 
        return 0;
 }
@@ -435,68 +462,50 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
        struct pwc_device *pdev = video_drvdata(file);
-       int ret, fps, snapshot, compression, pixelformat;
-
-       if (!pdev->udev)
-               return -ENODEV;
+       int ret, pixelformat, compression = 0;
 
-       if (pdev->capt_file != NULL &&
-           pdev->capt_file != file)
+       if (pwc_test_n_set_capt_file(pdev, file))
                return -EBUSY;
 
-       pdev->capt_file = file;
-
        ret = pwc_vidioc_try_fmt(pdev, f);
-       if (ret<0)
+       if (ret < 0)
                return ret;
 
        pixelformat = f->fmt.pix.pixelformat;
-       compression = pdev->vcompression;
-       snapshot = 0;
-       fps = pdev->vframes;
-       if (f->fmt.pix.priv) {
-               compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
-               snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
-               fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-               if (fps == 0)
-                       fps = pdev->vframes;
-       }
 
-       if (pixelformat != V4L2_PIX_FMT_YUV420 &&
-           pixelformat != V4L2_PIX_FMT_PWC1 &&
-           pixelformat != V4L2_PIX_FMT_PWC2)
-               return -EINVAL;
+       mutex_lock(&pdev->udevlock);
+       if (!pdev->udev) {
+               ret = -ENODEV;
+               goto leave;
+       }
 
-       if (vb2_is_streaming(&pdev->vb_queue))
-               return -EBUSY;
+       if (pdev->iso_init) {
+               ret = -EBUSY;
+               goto leave;
+       }
 
        PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
-                       "compression=%d snapshot=%d format=%c%c%c%c\n",
-                       f->fmt.pix.width, f->fmt.pix.height, fps,
-                       compression, snapshot,
+                       "format=%c%c%c%c\n",
+                       f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
                        (pixelformat)&255,
                        (pixelformat>>8)&255,
                        (pixelformat>>16)&255,
                        (pixelformat>>24)&255);
 
-       ret = pwc_set_video_mode(pdev,
-                                f->fmt.pix.width,
-                                f->fmt.pix.height,
-                                fps,
-                                compression,
-                                snapshot);
+       ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
+                                pdev->vframes, &compression);
 
        PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
 
-       if (ret)
-               return ret;
-
-       pdev->pixfmt = pixelformat;
-
-       pwc_vidioc_fill_fmt(pdev, f);
-
-       return 0;
+       if (ret == 0) {
+               pdev->pixfmt = pixelformat;
+               pwc_vidioc_fill_fmt(f, pdev->width, pdev->height,
+                                   pdev->pixfmt);
+       }
 
+leave:
+       mutex_unlock(&pdev->udevlock);
+       return ret;
 }
 
 static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
@@ -536,30 +545,14 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i)
        return i ? -EINVAL : 0;
 }
 
-static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl)
 {
        struct pwc_device *pdev =
                container_of(ctrl->handler, struct pwc_device, ctrl_handler);
        int ret = 0;
 
-       /*
-        * Sometimes it can take quite long for the pwc to complete usb control
-        * transfers, so release the modlock to give streaming by another
-        * process / thread the chance to continue with a dqbuf.
-        */
-       mutex_unlock(&pdev->modlock);
-
-       /*
-        * Take the udev-lock to protect against the disconnect handler
-        * completing and setting dev->udev to NULL underneath us. Other code
-        * does not need to do this since it is protected by the modlock.
-        */
-       mutex_lock(&pdev->udevlock);
-
-       if (!pdev->udev) {
-               ret = -ENODEV;
-               goto leave;
-       }
+       if (!pdev->udev)
+               return -ENODEV;
 
        switch (ctrl->id) {
        case V4L2_CID_AUTO_WHITE_BALANCE:
@@ -624,9 +617,18 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
        if (ret)
                PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
 
-leave:
+       return ret;
+}
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct pwc_device *pdev =
+               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+       int ret;
+
+       mutex_lock(&pdev->udevlock);
+       ret = pwc_g_volatile_ctrl_unlocked(ctrl);
        mutex_unlock(&pdev->udevlock);
-       mutex_lock(&pdev->modlock);
        return ret;
 }
 
@@ -643,6 +645,15 @@ static int pwc_set_awb(struct pwc_device *pdev)
 
                if (pdev->auto_white_balance->val != awb_manual)
                        pdev->color_bal_valid = false; /* Force cache update */
+
+               /*
+                * If this is a preset, update our red / blue balance values
+                * so that events get generated for the new preset values
+                */
+               if (pdev->auto_white_balance->val == awb_indoor ||
+                   pdev->auto_white_balance->val == awb_outdoor ||
+                   pdev->auto_white_balance->val == awb_fl)
+                       pwc_g_volatile_ctrl_unlocked(pdev->auto_white_balance);
        }
        if (pdev->auto_white_balance->val != awb_manual)
                return 0;
@@ -806,8 +817,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
                container_of(ctrl->handler, struct pwc_device, ctrl_handler);
        int ret = 0;
 
-       /* See the comments on locking in pwc_g_volatile_ctrl */
-       mutex_unlock(&pdev->modlock);
        mutex_lock(&pdev->udevlock);
 
        if (!pdev->udev) {
@@ -891,6 +900,16 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
                ret = pwc_button_ctrl(pdev,
                                      RESTORE_FACTORY_DEFAULTS_FORMATTER);
                break;
+       case PWC_CID_CUSTOM(awb_speed):
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     AWB_CONTROL_SPEED_FORMATTER,
+                                     ctrl->val);
+               break;
+       case PWC_CID_CUSTOM(awb_delay):
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     AWB_CONTROL_DELAY_FORMATTER,
+                                     ctrl->val);
+               break;
        case V4L2_CID_PAN_RELATIVE:
                ret = pwc_set_motor(pdev);
                break;
@@ -903,7 +922,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
 
 leave:
        mutex_unlock(&pdev->udevlock);
-       mutex_lock(&pdev->modlock);
        return ret;
 }
 
@@ -933,9 +951,14 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
        struct pwc_device *pdev = video_drvdata(file);
 
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */
        PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
-                       pdev->image.x, pdev->image.y);
-       pwc_vidioc_fill_fmt(pdev, f);
+                       pdev->width, pdev->height);
+       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+       mutex_unlock(&pdev->udevlock);
        return 0;
 }
 
@@ -951,12 +974,9 @@ static int pwc_reqbufs(struct file *file, void *fh,
 {
        struct pwc_device *pdev = video_drvdata(file);
 
-       if (pdev->capt_file != NULL &&
-           pdev->capt_file != file)
+       if (pwc_test_n_set_capt_file(pdev, file))
                return -EBUSY;
 
-       pdev->capt_file = file;
-
        return vb2_reqbufs(&pdev->vb_queue, rb);
 }
 
@@ -1025,25 +1045,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh,
        struct pwc_device *pdev = video_drvdata(file);
        unsigned int i = 0, index = fsize->index;
 
-       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
+       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
+           (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
+                       DEVICE_USE_CODEC1(pdev->type)) ||
+           (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
+                       DEVICE_USE_CODEC23(pdev->type))) {
                for (i = 0; i < PSZ_MAX; i++) {
-                       if (pdev->image_mask & (1UL << i)) {
-                               if (!index--) {
-                                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                                       fsize->discrete.width = pwc_image_sizes[i].x;
-                                       fsize->discrete.height = pwc_image_sizes[i].y;
-                                       return 0;
-                               }
+                       if (!(pdev->image_mask & (1UL << i)))
+                               continue;
+                       if (!index--) {
+                               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+                               fsize->discrete.width = pwc_image_sizes[i][0];
+                               fsize->discrete.height = pwc_image_sizes[i][1];
+                               return 0;
                        }
                }
-       } else if (fsize->index == 0 &&
-                       ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
-                        (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
-
-               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-               fsize->discrete.width = pdev->abs_max.x;
-               fsize->discrete.height = pdev->abs_max.y;
-               return 0;
        }
        return -EINVAL;
 }
@@ -1056,8 +1072,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
        unsigned int i;
 
        for (i = 0; i < PSZ_MAX; i++) {
-               if (pwc_image_sizes[i].x == fival->width &&
-                               pwc_image_sizes[i].y == fival->height) {
+               if (pwc_image_sizes[i][0] == fival->width &&
+                               pwc_image_sizes[i][1] == fival->height) {
                        size = i;
                        break;
                }
@@ -1086,14 +1102,6 @@ static int pwc_log_status(struct file *file, void *priv)
        return 0;
 }
 
-static long pwc_default(struct file *file, void *fh, bool valid_prio,
-                       int cmd, void *arg)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       return pwc_ioctl(pdev, cmd, arg);
-}
-
 const struct v4l2_ioctl_ops pwc_ioctl_ops = {
        .vidioc_querycap                    = pwc_querycap,
        .vidioc_enum_input                  = pwc_enum_input,
@@ -1112,8 +1120,4 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
        .vidioc_log_status                  = pwc_log_status,
        .vidioc_enum_framesizes             = pwc_enum_framesizes,
        .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
-       .vidioc_default             = pwc_default,
 };
-
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 0e4e2d7b78720a0c954bc0d5db9df787f7c813b4..47c518fef179949be25f50c51eac12f95ea7c819 100644 (file)
 #include <asm/errno.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
 #include <media/videobuf2-vmalloc.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/input.h>
 #endif
 
-#include <media/pwc-ioctl.h>
-
 /* Version block */
 #define PWC_VERSION    "10.0.15"
 #define PWC_NAME       "pwc"
 #define FEATURE_CODEC1                 0x0002
 #define FEATURE_CODEC2                 0x0004
 
+#define MAX_WIDTH              640
+#define MAX_HEIGHT             480
+
 /* Ignore errors in the first N frames, to allow for startup delays */
 #define FRAME_LOWMARK 5
 
 #define PT_RESET_CONTROL_FORMATTER             0x02
 #define PT_STATUS_FORMATTER                    0x03
 
+/* Enumeration of image sizes */
+#define PSZ_SQCIF      0x00
+#define PSZ_QSIF       0x01
+#define PSZ_QCIF       0x02
+#define PSZ_SIF                0x03
+#define PSZ_CIF                0x04
+#define PSZ_VGA                0x05
+#define PSZ_MAX                6
+
+struct pwc_raw_frame {
+       __le16 type;            /* type of the webcam */
+       __le16 vbandlength;     /* Size of 4 lines compressed (used by the
+                                  decompressor) */
+       __u8   cmd[4];          /* the four byte of the command (in case of
+                                  nala, only the first 3 bytes is filled) */
+       __u8   rawframe[0];     /* frame_size = H / 4 * vbandlength */
+} __packed;
+
 /* intermediate buffers with raw data from the USB cam */
 struct pwc_frame_buf
 {
@@ -198,33 +220,30 @@ struct pwc_frame_buf
 struct pwc_device
 {
        struct video_device vdev;
-       struct mutex modlock;
+       struct v4l2_device v4l2_dev;
 
        /* Pointer to our usb_device, may be NULL after unplug */
        struct usb_device *udev;
-       /* Protects the setting of udev to NULL by our disconnect handler */
        struct mutex udevlock;
 
        /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
        int type;
        int release;            /* release number */
        int features;           /* feature bits */
-       char serial[30];        /* serial number (string) */
 
        /*** Video data ***/
        struct file *capt_file; /* file doing video capture */
+       struct mutex capt_file_lock;
        int vendpoint;          /* video isoc endpoint */
        int vcinterface;        /* video control interface */
        int valternate;         /* alternate interface needed */
-       int vframes, vsize;     /* frames-per-second & size (see PSZ_*) */
+       int vframes;            /* frames-per-second */
        int pixfmt;             /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
        int vframe_count;       /* received frames */
        int vmax_packet_size;   /* USB maxpacket size */
        int vlast_packet_size;  /* for frame synchronisation */
        int visoc_errors;       /* number of contiguous ISOC errors */
-       int vcompression;       /* desired compression factor */
        int vbandlength;        /* compressed band length; 0 is uncompressed */
-       char vsnapshot;         /* snapshot mode */
        char vsync;             /* used by isoc handler */
        char vmirror;           /* for ToUCaM series */
        char power_save;        /* Do powersaving for this cam */
@@ -262,21 +281,8 @@ struct pwc_device
         * a gray or black border. view_min <= image <= view <= view_max;
         */
        int image_mask;                         /* supported sizes */
-       struct pwc_coord view_min, view_max;    /* minimum and maximum view */
-       struct pwc_coord abs_max;               /* maximum supported size */
-       struct pwc_coord image, view;           /* image and viewport size */
-       struct pwc_coord offset;                /* offset of the viewport */
-
-       /*** motorized pan/tilt feature */
-       struct pwc_mpt_range angle_range;
-       int pan_angle;                  /* in degrees * 100 */
-       int tilt_angle;                 /* absolute angle; 0,0 is home */
+       int width, height;                      /* current resolution */
 
-       /*
-        * Set to 1 when the user push the button, reset to 0
-        * when this value is read from sysfs.
-        */
-       int snapshot_button_status;
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
        struct input_dev *button_dev;   /* webcam snapshot button input */
        char button_phys[64];
@@ -328,6 +334,8 @@ struct pwc_device
        struct v4l2_ctrl                *save_user;
        struct v4l2_ctrl                *restore_user;
        struct v4l2_ctrl                *restore_factory;
+       struct v4l2_ctrl                *awb_speed;
+       struct v4l2_ctrl                *awb_delay;
        struct {
                /* motor control cluster */
                struct v4l2_ctrl        *motor_pan;
@@ -344,19 +352,20 @@ struct pwc_device
 extern int pwc_trace;
 #endif
 
+int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file);
+
 /** Functions in pwc-misc.c */
 /* sizes in pixels */
-extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
+extern const int pwc_image_sizes[PSZ_MAX][2];
 
-int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+int pwc_get_size(struct pwc_device *pdev, int width, int height);
 void pwc_construct(struct pwc_device *pdev);
 
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
-extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+                             int frames, int *compression);
 extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
-extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
-extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
 extern int send_control_msg(struct pwc_device *pdev,
@@ -375,9 +384,6 @@ int pwc_init_controls(struct pwc_device *pdev);
 /* Power down or up the camera; not supported by all models */
 extern void pwc_camera_power(struct pwc_device *pdev, int power);
 
-/* Private ioctl()s; see pwc-ioctl.h */
-extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
-
 extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
 
 /** pwc-uncompress.c */
index 79fb22c89ae9f10a894722381c94fbaab2b884b7..0bd7da26d018142878c35956ae8c1126a44c5bfb 100644 (file)
@@ -1133,12 +1133,13 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
        __raw_writel(cicr0, pcdev->base + CICR0);
 }
 
-static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int pxa_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
        unsigned long bus_flags, common_flags;
        int ret;
        struct pxa_cam *cam = icd->host_priv;
@@ -1851,19 +1852,7 @@ static struct platform_driver pxa_camera_driver = {
        .remove         = __devexit_p(pxa_camera_remove),
 };
 
-
-static int __init pxa_camera_init(void)
-{
-       return platform_driver_register(&pxa_camera_driver);
-}
-
-static void __exit pxa_camera_exit(void)
-{
-       platform_driver_unregister(&pxa_camera_driver);
-}
-
-module_init(pxa_camera_init);
-module_exit(pxa_camera_exit);
+module_platform_driver(pxa_camera_driver);
 
 MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
index 2cc3b9166724f2eaf47ea1c05f5a12e5e7208ea7..510cfab477fff48c57ddd2d9151b53ec144f91ea 100644 (file)
@@ -63,6 +63,8 @@ static int fimc_init_capture(struct fimc_dev *fimc)
                fimc_hw_set_effect(ctx, false);
                fimc_hw_set_output_path(ctx);
                fimc_hw_set_out_dma(ctx);
+               if (fimc->variant->has_alpha)
+                       fimc_hw_set_rgb_alpha(ctx);
                clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
        }
        spin_unlock_irqrestore(&fimc->slock, flags);
@@ -154,6 +156,8 @@ int fimc_capture_config_update(struct fimc_ctx *ctx)
                fimc_hw_set_rotation(ctx);
                fimc_prepare_dma_offset(ctx, &ctx->d_frame);
                fimc_hw_set_out_dma(ctx);
+               if (fimc->variant->has_alpha)
+                       fimc_hw_set_rgb_alpha(ctx);
                clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
        }
        spin_unlock(&ctx->slock);
@@ -812,6 +816,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                                          FIMC_SD_PAD_SOURCE);
        if (!ff->fmt)
                return -EINVAL;
+
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        /* Try to match format at the host and the sensor */
        if (!fimc->vid_cap.user_subdev_api) {
                mf->code   = ff->fmt->mbus_code;
@@ -1235,6 +1243,9 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
                *mf = fmt->format;
                return 0;
        }
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
 
        ff = fmt->pad == FIMC_SD_PAD_SINK ?
index 07c6254faee32b1ef3ee75964faa2b63b1f7615d..f5cbb8a4c540fc7d6beac2891c36aa812f05f281 100644 (file)
@@ -52,13 +52,29 @@ static struct fimc_fmt fimc_formats[] = {
                .colplanes      = 1,
                .flags          = FMT_FLAGS_M2M,
        }, {
-               .name           = "XRGB-8-8-8-8, 32 bpp",
+               .name           = "ARGB8888, 32 bpp",
                .fourcc         = V4L2_PIX_FMT_RGB32,
                .depth          = { 32 },
                .color          = S5P_FIMC_RGB888,
                .memplanes      = 1,
                .colplanes      = 1,
-               .flags          = FMT_FLAGS_M2M,
+               .flags          = FMT_FLAGS_M2M | FMT_HAS_ALPHA,
+       }, {
+               .name           = "ARGB1555",
+               .fourcc         = V4L2_PIX_FMT_RGB555,
+               .depth          = { 16 },
+               .color          = S5P_FIMC_RGB555,
+               .memplanes      = 1,
+               .colplanes      = 1,
+               .flags          = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
+       }, {
+               .name           = "ARGB4444",
+               .fourcc         = V4L2_PIX_FMT_RGB444,
+               .depth          = { 16 },
+               .color          = S5P_FIMC_RGB444,
+               .memplanes      = 1,
+               .colplanes      = 1,
+               .flags          = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
        }, {
                .name           = "YUV 4:2:2 packed, YCbYCr",
                .fourcc         = V4L2_PIX_FMT_YUYV,
@@ -171,6 +187,14 @@ static struct fimc_fmt fimc_formats[] = {
        },
 };
 
+static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
+{
+       if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return FMT_FLAGS_M2M_IN;
+       else
+               return FMT_FLAGS_M2M_OUT;
+}
+
 int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
                            int dw, int dh, int rotation)
 {
@@ -652,8 +676,11 @@ static void fimc_dma_run(void *priv)
        if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
                fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
 
-       if (ctx->state & FIMC_PARAMS)
+       if (ctx->state & FIMC_PARAMS) {
                fimc_hw_set_out_dma(ctx);
+               if (fimc->variant->has_alpha)
+                       fimc_hw_set_rgb_alpha(ctx);
+       }
 
        fimc_activate_capture(ctx);
 
@@ -750,12 +777,11 @@ static struct vb2_ops fimc_qops = {
 #define ctrl_to_ctx(__ctrl) \
        container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
 
-static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
 {
-       struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct samsung_fimc_variant *variant = fimc->variant;
-       unsigned long flags;
+       unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT;
        int ret = 0;
 
        if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
@@ -763,52 +789,63 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_HFLIP:
-               spin_lock_irqsave(&ctx->slock, flags);
                ctx->hflip = ctrl->val;
                break;
 
        case V4L2_CID_VFLIP:
-               spin_lock_irqsave(&ctx->slock, flags);
                ctx->vflip = ctrl->val;
                break;
 
        case V4L2_CID_ROTATE:
                if (fimc_capture_pending(fimc) ||
-                   fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+                   (ctx->state & flags) == flags) {
                        ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
                                        ctx->s_frame.height, ctx->d_frame.width,
                                        ctx->d_frame.height, ctrl->val);
-               }
-               if (ret) {
-                       v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
-                       return -EINVAL;
+                       if (ret)
+                               return -EINVAL;
                }
                if ((ctrl->val == 90 || ctrl->val == 270) &&
                    !variant->has_out_rot)
                        return -EINVAL;
-               spin_lock_irqsave(&ctx->slock, flags);
+
                ctx->rotation = ctrl->val;
                break;
 
-       default:
-               v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
-               return -EINVAL;
+       case V4L2_CID_ALPHA_COMPONENT:
+               ctx->d_frame.alpha = ctrl->val;
+               break;
        }
        ctx->state |= FIMC_PARAMS;
        set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
-       spin_unlock_irqrestore(&ctx->slock, flags);
        return 0;
 }
 
+static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&ctx->slock, flags);
+       ret = __fimc_s_ctrl(ctx, ctrl);
+       spin_unlock_irqrestore(&ctx->slock, flags);
+
+       return ret;
+}
+
 static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
        .s_ctrl = fimc_s_ctrl,
 };
 
 int fimc_ctrls_create(struct fimc_ctx *ctx)
 {
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+       unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
        if (ctx->ctrls_rdy)
                return 0;
-       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
 
        ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
                                     V4L2_CID_HFLIP, 0, 1, 1, 0);
@@ -816,6 +853,13 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
                                    V4L2_CID_VFLIP, 0, 1, 1, 0);
        ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
                                    V4L2_CID_ROTATE, 0, 270, 90, 0);
+       if (variant->has_alpha)
+               ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                                   &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+                                   0, max_alpha, 1, 0);
+       else
+               ctx->ctrl_alpha = NULL;
+
        ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
 
        return ctx->ctrl_handler.error;
@@ -826,11 +870,14 @@ void fimc_ctrls_delete(struct fimc_ctx *ctx)
        if (ctx->ctrls_rdy) {
                v4l2_ctrl_handler_free(&ctx->ctrl_handler);
                ctx->ctrls_rdy = false;
+               ctx->ctrl_alpha = NULL;
        }
 }
 
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
 {
+       unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
+
        if (!ctx->ctrls_rdy)
                return;
 
@@ -838,6 +885,8 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
        v4l2_ctrl_activate(ctx->ctrl_rotate, active);
        v4l2_ctrl_activate(ctx->ctrl_hflip, active);
        v4l2_ctrl_activate(ctx->ctrl_vflip, active);
+       if (ctx->ctrl_alpha)
+               v4l2_ctrl_activate(ctx->ctrl_alpha, active && has_alpha);
 
        if (active) {
                ctx->rotation = ctx->ctrl_rotate->val;
@@ -851,6 +900,24 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
        mutex_unlock(&ctx->ctrl_handler.lock);
 }
 
+/* Update maximum value of the alpha color control */
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
+{
+       struct fimc_dev *fimc = ctx->fimc_dev;
+       struct v4l2_ctrl *ctrl = ctx->ctrl_alpha;
+
+       if (ctrl == NULL || !fimc->variant->has_alpha)
+               return;
+
+       v4l2_ctrl_lock(ctrl);
+       ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
+       if (ctrl->cur.val > ctrl->maximum)
+               ctrl->cur.val = ctrl->maximum;
+
+       v4l2_ctrl_unlock(ctrl);
+}
+
 /*
  * V4L2 ioctl handlers
  */
@@ -874,7 +941,8 @@ static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
 {
        struct fimc_fmt *fmt;
 
-       fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index);
+       fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
+                              f->index);
        if (!fmt)
                return -EINVAL;
 
@@ -938,6 +1006,7 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
        pix->colorspace = V4L2_COLORSPACE_JPEG;
        pix->field = V4L2_FIELD_NONE;
        pix->num_planes = fmt->memplanes;
+       pix->pixelformat = fmt->fourcc;
        pix->height = height;
        pix->width = width;
 
@@ -1017,7 +1086,8 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
 
        dbg("w: %d, h: %d", pix->width, pix->height);
 
-       fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0);
+       fmt = fimc_find_format(&pix->pixelformat, NULL,
+                              get_m2m_fmt_flags(f->type), 0);
        if (WARN(fmt == NULL, "Pixel format lookup failed"))
                return -EINVAL;
 
@@ -1087,10 +1157,13 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
 
        pix = &f->fmt.pix_mp;
        frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
-                                     FMT_FLAGS_M2M, 0);
+                                     get_m2m_fmt_flags(f->type), 0);
        if (!frame->fmt)
                return -EINVAL;
 
+       /* Update RGB Alpha control state and value range */
+       fimc_alpha_ctrl_update(ctx);
+
        for (i = 0; i < frame->fmt->colplanes; i++) {
                frame->payload[i] =
                        (pix->width * pix->height * frame->fmt->depth[i]) / 8;
@@ -1374,6 +1447,12 @@ static int fimc_m2m_open(struct file *file)
        if (!ctx)
                return -ENOMEM;
        v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+       ctx->fimc_dev = fimc;
+
+       /* Default color format */
+       ctx->s_frame.fmt = &fimc_formats[0];
+       ctx->d_frame.fmt = &fimc_formats[0];
+
        ret = fimc_ctrls_create(ctx);
        if (ret)
                goto error_fh;
@@ -1383,10 +1462,6 @@ static int fimc_m2m_open(struct file *file)
        file->private_data = &ctx->fh;
        v4l2_fh_add(&ctx->fh);
 
-       ctx->fimc_dev = fimc;
-       /* Default color format */
-       ctx->s_frame.fmt = &fimc_formats[0];
-       ctx->d_frame.fmt = &fimc_formats[0];
        /* Setup the device context for memory-to-memory mode */
        ctx->state = FIMC_CTX_M2M;
        ctx->flags = 0;
@@ -1709,9 +1784,8 @@ static int fimc_runtime_resume(struct device *dev)
        /* Resume the capture or mem-to-mem device */
        if (fimc_capture_busy(fimc))
                return fimc_capture_resume(fimc);
-       else if (fimc_m2m_pending(fimc))
-               return fimc_m2m_resume(fimc);
-       return 0;
+
+       return fimc_m2m_resume(fimc);
 }
 
 static int fimc_runtime_suspend(struct device *dev)
@@ -1893,6 +1967,7 @@ static struct samsung_fimc_variant fimc0_variant_exynos4 = {
        .has_cam_if      = 1,
        .has_cistatus2   = 1,
        .has_mainscaler_ext = 1,
+       .has_alpha       = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 2,
@@ -1906,6 +1981,7 @@ static struct samsung_fimc_variant fimc3_variant_exynos4 = {
        .has_cam_if      = 1,
        .has_cistatus2   = 1,
        .has_mainscaler_ext = 1,
+       .has_alpha       = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 2,
index c7f01c47b20fe354e101bbf4ab904cab18e3ec55..4e20560c73d4d5ed6e74e81c324cd5ca7cc062ca 100644 (file)
@@ -85,7 +85,9 @@ enum fimc_datapath {
 };
 
 enum fimc_color_fmt {
-       S5P_FIMC_RGB565 = 0x10,
+       S5P_FIMC_RGB444 = 0x10,
+       S5P_FIMC_RGB555,
+       S5P_FIMC_RGB565,
        S5P_FIMC_RGB666,
        S5P_FIMC_RGB888,
        S5P_FIMC_RGB30_LOCAL,
@@ -160,8 +162,11 @@ struct fimc_fmt {
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
        u16     flags;
-#define FMT_FLAGS_CAM  (1 << 0)
-#define FMT_FLAGS_M2M  (1 << 1)
+#define FMT_FLAGS_CAM          (1 << 0)
+#define FMT_FLAGS_M2M_IN       (1 << 1)
+#define FMT_FLAGS_M2M_OUT      (1 << 2)
+#define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
+#define FMT_HAS_ALPHA          (1 << 3)
 };
 
 /**
@@ -283,6 +288,7 @@ struct fimc_frame {
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
+       u8                      alpha;
 };
 
 /**
@@ -387,6 +393,7 @@ struct samsung_fimc_variant {
        unsigned int    has_cistatus2:1;
        unsigned int    has_mainscaler_ext:1;
        unsigned int    has_cam_if:1;
+       unsigned int    has_alpha:1;
        struct fimc_pix_limit *pix_limit;
        u16             min_inp_pixsize;
        u16             min_out_pixsize;
@@ -482,7 +489,8 @@ struct fimc_dev {
  * @ctrl_handler:      v4l2 controls handler
  * @ctrl_rotate                image rotation control
  * @ctrl_hflip         horizontal flip control
- * @ctrl_vflip         vartical flip control
+ * @ctrl_vflip         vertical flip control
+ * @ctrl_alpha         RGB alpha control
  * @ctrls_rdy:         true if the control handler is initialized
  */
 struct fimc_ctx {
@@ -509,6 +517,7 @@ struct fimc_ctx {
        struct v4l2_ctrl        *ctrl_rotate;
        struct v4l2_ctrl        *ctrl_hflip;
        struct v4l2_ctrl        *ctrl_vflip;
+       struct v4l2_ctrl        *ctrl_alpha;
        bool                    ctrls_rdy;
 };
 
@@ -578,6 +587,17 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+/* Return the alpha component bit mask */
+static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
+{
+       switch (fmt->color) {
+       case S5P_FIMC_RGB444:   return 0x0f;
+       case S5P_FIMC_RGB555:   return 0x01;
+       case S5P_FIMC_RGB888:   return 0xff;
+       default:                return 0;
+       };
+}
+
 static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
 {
        u32 cfg = readl(dev->regs + S5P_CIGCTRL);
@@ -674,6 +694,7 @@ void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
 void fimc_hw_en_capture(struct fimc_ctx *ctx);
 void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active);
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
 void fimc_hw_set_input_path(struct fimc_ctx *ctx);
 void fimc_hw_set_output_path(struct fimc_ctx *ctx);
@@ -695,6 +716,7 @@ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
 int fimc_ctrls_create(struct fimc_ctx *ctx);
 void fimc_ctrls_delete(struct fimc_ctx *ctx);
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx);
 int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
 void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
                               struct v4l2_pix_format_mplane *pix);
index 44f5c2d1920bb50dd0dfe8e436eec1df32aa8c3f..15466d0529c14907e2cf2716cd49b1f1da03e8f5 100644 (file)
@@ -117,7 +117,7 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
                  S5P_CITRGFMT_VSIZE_MASK);
 
        switch (frame->fmt->color) {
-       case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
+       case S5P_FIMC_RGB444...S5P_FIMC_RGB888:
                cfg |= S5P_CITRGFMT_RGB;
                break;
        case S5P_FIMC_YCBCR420:
@@ -175,6 +175,7 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
        struct fimc_dev *dev = ctx->fimc_dev;
        struct fimc_frame *frame = &ctx->d_frame;
        struct fimc_dma_offset *offset = &frame->dma_offset;
+       struct fimc_fmt *fmt = frame->fmt;
 
        /* Set the input dma offsets. */
        cfg = 0;
@@ -198,15 +199,22 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
        cfg = readl(dev->regs + S5P_CIOCTRL);
 
        cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
-                S5P_CIOCTRL_YCBCR_PLANE_MASK);
+                S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK);
 
-       if (frame->fmt->colplanes == 1)
+       if (fmt->colplanes == 1)
                cfg |= ctx->out_order_1p;
-       else if (frame->fmt->colplanes == 2)
+       else if (fmt->colplanes == 2)
                cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
-       else if (frame->fmt->colplanes == 3)
+       else if (fmt->colplanes == 3)
                cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
 
+       if (fmt->color == S5P_FIMC_RGB565)
+               cfg |= S5P_CIOCTRL_RGB565;
+       else if (fmt->color == S5P_FIMC_RGB555)
+               cfg |= S5P_CIOCTRL_ARGB1555;
+       else if (fmt->color == S5P_FIMC_RGB444)
+               cfg |= S5P_CIOCTRL_ARGB4444;
+
        writel(cfg, dev->regs + S5P_CIOCTRL);
 }
 
@@ -278,22 +286,28 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
        if (sc->copy_mode)
                cfg |= S5P_CISCCTRL_ONE2ONE;
 
-
        if (ctx->in_path == FIMC_DMA) {
-               if (src_frame->fmt->color == S5P_FIMC_RGB565)
+               switch (src_frame->fmt->color) {
+               case S5P_FIMC_RGB565:
                        cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
-               else if (src_frame->fmt->color == S5P_FIMC_RGB666)
+                       break;
+               case S5P_FIMC_RGB666:
                        cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
-               else if (src_frame->fmt->color == S5P_FIMC_RGB888)
+                       break;
+               case S5P_FIMC_RGB888:
                        cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
+                       break;
+               }
        }
 
        if (ctx->out_path == FIMC_DMA) {
-               if (dst_frame->fmt->color == S5P_FIMC_RGB565)
+               u32 color = dst_frame->fmt->color;
+
+               if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565)
                        cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
-               else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
+               else if (color == S5P_FIMC_RGB666)
                        cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
-               else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
+               else if (color == S5P_FIMC_RGB888)
                        cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
        } else {
                cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
@@ -379,6 +393,21 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
        writel(cfg, dev->regs + S5P_CIIMGEFF);
 }
 
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
+{
+       struct fimc_dev *dev = ctx->fimc_dev;
+       struct fimc_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       if (!(frame->fmt->flags & FMT_HAS_ALPHA))
+               return;
+
+       cfg = readl(dev->regs + S5P_CIOCTRL);
+       cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK;
+       cfg |= (frame->alpha << 4);
+       writel(cfg, dev->regs + S5P_CIOCTRL);
+}
+
 static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev = ctx->fimc_dev;
index 59d79bc2f58a243c1de3cfa15b3af40b10c4cbaa..130335cf62fdc391fbb7862348b76832f6cbdbb3 100644 (file)
@@ -427,6 +427,23 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+       format->colorspace = V4L2_COLORSPACE_JPEG;
+       format->code = s5pcsis_formats[0].code;
+       format->width = S5PCSIS_DEF_PIX_WIDTH;
+       format->height = S5PCSIS_DEF_PIX_HEIGHT;
+       format->field = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
+       .open = s5pcsis_open,
+};
+
 static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
        .s_power = s5pcsis_s_power,
 };
@@ -544,8 +561,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
        v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
        state->sd.owner = THIS_MODULE;
        strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
+       state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
        state->csis_fmt = &s5pcsis_formats[0];
 
+       state->format.code = s5pcsis_formats[0].code;
+       state->format.width = S5PCSIS_DEF_PIX_WIDTH;
+       state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
+
        state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
        state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
        ret = media_entity_init(&state->sd.entity,
index f5691336dd5cb6b9dd3f6ed54540522dc7bae507..2709286396e1db8fa5ea963e8d802dd9571ee018 100644 (file)
@@ -19,4 +19,7 @@
 #define CSIS_PAD_SOURCE                1
 #define CSIS_PADS_NUM          2
 
+#define S5PCSIS_DEF_PIX_WIDTH  640
+#define S5PCSIS_DEF_PIX_HEIGHT 480
+
 #endif
index c8e3b94bd91d2ca7cf16c66886a33c9afbe1c290..c7a5bc51d571d860d6daee44a0076b99216d388f 100644 (file)
 #define S5P_CIOCTRL_YCBCR_3PLANE       (0 << 3)
 #define S5P_CIOCTRL_YCBCR_2PLANE       (1 << 3)
 #define S5P_CIOCTRL_YCBCR_PLANE_MASK   (1 << 3)
+#define S5P_CIOCTRL_ALPHA_OUT_MASK     (0xff << 4)
+#define S5P_CIOCTRL_RGB16FMT_MASK      (3 << 16)
+#define S5P_CIOCTRL_RGB565             (0 << 16)
+#define S5P_CIOCTRL_ARGB1555           (1 << 16)
+#define S5P_CIOCTRL_ARGB4444           (2 << 16)
 #define S5P_CIOCTRL_ORDER2P_SHIFT      (24)
 #define S5P_CIOCTRL_ORDER2P_MASK       (3 << 24)
 #define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
diff --git a/drivers/media/video/s5p-g2d/Makefile b/drivers/media/video/s5p-g2d/Makefile
new file mode 100644 (file)
index 0000000..2c48c41
--- /dev/null
@@ -0,0 +1,3 @@
+s5p-g2d-objs := g2d.o g2d-hw.o
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)    += s5p-g2d.o
diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/video/s5p-g2d/g2d-hw.c
new file mode 100644 (file)
index 0000000..39937cf
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version
+ */
+
+#include <linux/io.h>
+
+#include "g2d.h"
+#include "g2d-regs.h"
+
+#define w(x, a)        writel((x), d->regs + (a))
+#define r(a)   readl(d->regs + (a))
+
+/* g2d_reset clears all g2d registers */
+void g2d_reset(struct g2d_dev *d)
+{
+       w(1, SOFT_RESET_REG);
+}
+
+void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f)
+{
+       u32 n;
+
+       w(f->stride & 0xFFFF, SRC_STRIDE_REG);
+
+       n = f->o_height & 0xFFF;
+       n <<= 16;
+       n |= f->o_width & 0xFFF;
+       w(n, SRC_LEFT_TOP_REG);
+
+       n = f->bottom & 0xFFF;
+       n <<= 16;
+       n |= f->right & 0xFFF;
+       w(n, SRC_RIGHT_BOTTOM_REG);
+
+       w(f->fmt->hw, SRC_COLOR_MODE_REG);
+}
+
+void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a)
+{
+       w(a, SRC_BASE_ADDR_REG);
+}
+
+void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
+{
+       u32 n;
+
+       w(f->stride & 0xFFFF, DST_STRIDE_REG);
+
+       n = f->o_height & 0xFFF;
+       n <<= 16;
+       n |= f->o_width & 0xFFF;
+       w(n, DST_LEFT_TOP_REG);
+
+       n = f->bottom & 0xFFF;
+       n <<= 16;
+       n |= f->right & 0xFFF;
+       w(n, DST_RIGHT_BOTTOM_REG);
+
+       w(f->fmt->hw, DST_COLOR_MODE_REG);
+}
+
+void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a)
+{
+       w(a, DST_BASE_ADDR_REG);
+}
+
+void g2d_set_rop4(struct g2d_dev *d, u32 r)
+{
+       w(r, ROP4_REG);
+}
+
+u32 g2d_cmd_stretch(u32 e)
+{
+       e &= 1;
+       return e << 4;
+}
+
+void g2d_set_cmd(struct g2d_dev *d, u32 c)
+{
+       w(c, BITBLT_COMMAND_REG);
+}
+
+void g2d_start(struct g2d_dev *d)
+{
+       /* Clear cache */
+       w(0x7, CACHECTL_REG);
+       /* Enable interrupt */
+       w(1, INTEN_REG);
+       /* Start G2D engine */
+       w(1, BITBLT_START_REG);
+}
+
+void g2d_clear_int(struct g2d_dev *d)
+{
+       w(1, INTC_PEND_REG);
+}
diff --git a/drivers/media/video/s5p-g2d/g2d-regs.h b/drivers/media/video/s5p-g2d/g2d-regs.h
new file mode 100644 (file)
index 0000000..02e1cf5
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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
+ */
+
+/* General Registers */
+#define SOFT_RESET_REG         0x0000  /* Software reset reg */
+#define INTEN_REG              0x0004  /* Interrupt Enable reg */
+#define INTC_PEND_REG          0x000C  /* Interrupt Control Pending reg */
+#define FIFO_STAT_REG          0x0010  /* Command FIFO Status reg */
+#define AXI_ID_MODE_REG                0x0014  /* AXI Read ID Mode reg */
+#define CACHECTL_REG           0x0018  /* Cache & Buffer clear reg */
+#define AXI_MODE_REG           0x001C  /* AXI Mode reg */
+
+/* Command Registers */
+#define BITBLT_START_REG       0x0100  /* BitBLT Start reg */
+#define BITBLT_COMMAND_REG     0x0104  /* Command reg for BitBLT */
+
+/* Parameter Setting Registers (Rotate & Direction) */
+#define ROTATE_REG             0x0200  /* Rotation reg */
+#define SRC_MSK_DIRECT_REG     0x0204  /* Src and Mask Direction reg */
+#define DST_PAT_DIRECT_REG     0x0208  /* Dest and Pattern Direction reg */
+
+/* Parameter Setting Registers (Src) */
+#define SRC_SELECT_REG         0x0300  /* Src Image Selection reg */
+#define SRC_BASE_ADDR_REG      0x0304  /* Src Image Base Address reg */
+#define SRC_STRIDE_REG         0x0308  /* Src Stride reg */
+#define SRC_COLOR_MODE_REG     0x030C  /* Src Image Color Mode reg */
+#define SRC_LEFT_TOP_REG       0x0310  /* Src Left Top Coordinate reg */
+#define SRC_RIGHT_BOTTOM_REG   0x0314  /* Src Right Bottom Coordinate reg */
+
+/* Parameter Setting Registers (Dest) */
+#define DST_SELECT_REG         0x0400  /* Dest Image Selection reg */
+#define DST_BASE_ADDR_REG      0x0404  /* Dest Image Base Address reg */
+#define DST_STRIDE_REG         0x0408  /* Dest Stride reg */
+#define DST_COLOR_MODE_REG     0x040C  /* Dest Image Color Mode reg */
+#define DST_LEFT_TOP_REG       0x0410  /* Dest Left Top Coordinate reg */
+#define DST_RIGHT_BOTTOM_REG   0x0414  /* Dest Right Bottom Coordinate reg */
+
+/* Parameter Setting Registers (Pattern) */
+#define PAT_BASE_ADDR_REG      0x0500  /* Pattern Image Base Address reg */
+#define PAT_SIZE_REG           0x0504  /* Pattern Image Size reg */
+#define PAT_COLOR_MODE_REG     0x0508  /* Pattern Image Color Mode reg */
+#define PAT_OFFSET_REG         0x050C  /* Pattern Left Top Coordinate reg */
+#define PAT_STRIDE_REG         0x0510  /* Pattern Stride reg */
+
+/* Parameter Setting Registers (Mask) */
+#define MASK_BASE_ADDR_REG     0x0520  /* Mask Base Address reg */
+#define MASK_STRIDE_REG                0x0524  /* Mask Stride reg */
+
+/* Parameter Setting Registers (Clipping Window) */
+#define CW_LT_REG              0x0600  /* LeftTop coordinates of Clip Window */
+#define CW_RB_REG              0x0604  /* RightBottom coordinates of Clip
+                                                               Window */
+
+/* Parameter Setting Registers (ROP & Alpha Setting) */
+#define THIRD_OPERAND_REG      0x0610  /* Third Operand Selection reg */
+#define ROP4_REG               0x0614  /* Raster Operation reg */
+#define ALPHA_REG              0x0618  /* Alpha value, Fading offset value */
+
+/* Parameter Setting Registers (Color) */
+#define FG_COLOR_REG           0x0700  /* Foreground Color reg */
+#define BG_COLOR_REG           0x0704  /* Background Color reg */
+#define BS_COLOR_REG           0x0708  /* Blue Screen Color reg */
+
+/* Parameter Setting Registers (Color Key) */
+#define SRC_COLORKEY_CTRL_REG  0x0710  /* Src Colorkey control reg */
+#define SRC_COLORKEY_DR_MIN_REG        0x0714  /* Src Colorkey Decision Reference
+                                                               Min reg */
+#define SRC_COLORKEY_DR_MAX_REG        0x0718  /* Src Colorkey Decision Reference
+                                                               Max reg */
+#define DST_COLORKEY_CTRL_REG  0x071C  /* Dest Colorkey control reg */
+#define DST_COLORKEY_DR_MIN_REG        0x0720  /* Dest Colorkey Decision Reference
+                                                               Min reg */
+#define DST_COLORKEY_DR_MAX_REG        0x0724  /* Dest Colorkey Decision Reference
+                                                               Max reg */
+
+/* Color mode values */
+
+#define ORDER_XRGB             0
+#define ORDER_RGBX             1
+#define ORDER_XBGR             2
+#define ORDER_BGRX             3
+
+#define MODE_XRGB_8888         0
+#define MODE_ARGB_8888         1
+#define MODE_RGB_565           2
+#define MODE_XRGB_1555         3
+#define MODE_ARGB_1555         4
+#define MODE_XRGB_4444         5
+#define MODE_ARGB_4444         6
+#define MODE_PACKED_RGB_888    7
+
+#define COLOR_MODE(o, m)       (((o) << 4) | (m))
+
+/* ROP4 operation values */
+#define ROP4_COPY              0xCCCC
+#define ROP4_INVERT            0x3333
+
+/* Hardware limits */
+#define MAX_WIDTH              8000
+#define MAX_HEIGHT             8000
+
+#define G2D_TIMEOUT            500
+
+#define DEFAULT_WIDTH          100
+#define DEFAULT_HEIGHT         100
+
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
new file mode 100644 (file)
index 0000000..c40b0dd
--- /dev/null
@@ -0,0 +1,810 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "g2d.h"
+#include "g2d-regs.h"
+
+#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh)
+
+static struct g2d_fmt formats[] = {
+       {
+               .name   = "XRGB_8888",
+               .fourcc = V4L2_PIX_FMT_RGB32,
+               .depth  = 32,
+               .hw     = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888),
+       },
+       {
+               .name   = "RGB_565",
+               .fourcc = V4L2_PIX_FMT_RGB565X,
+               .depth  = 16,
+               .hw     = COLOR_MODE(ORDER_XRGB, MODE_RGB_565),
+       },
+       {
+               .name   = "XRGB_1555",
+               .fourcc = V4L2_PIX_FMT_RGB555X,
+               .depth  = 16,
+               .hw     = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555),
+       },
+       {
+               .name   = "XRGB_4444",
+               .fourcc = V4L2_PIX_FMT_RGB444,
+               .depth  = 16,
+               .hw     = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444),
+       },
+       {
+               .name   = "PACKED_RGB_888",
+               .fourcc = V4L2_PIX_FMT_RGB24,
+               .depth  = 24,
+               .hw     = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888),
+       },
+};
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+struct g2d_frame def_frame = {
+       .width          = DEFAULT_WIDTH,
+       .height         = DEFAULT_HEIGHT,
+       .c_width        = DEFAULT_WIDTH,
+       .c_height       = DEFAULT_HEIGHT,
+       .o_width        = 0,
+       .o_height       = 0,
+       .fmt            = &formats[0],
+       .right          = DEFAULT_WIDTH,
+       .bottom         = DEFAULT_HEIGHT,
+};
+
+struct g2d_fmt *find_fmt(struct v4l2_format *f)
+{
+       unsigned int i;
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].fourcc == f->fmt.pix.pixelformat)
+                       return &formats[i];
+       }
+       return NULL;
+}
+
+
+static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
+                                                       enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return &ctx->in;
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &ctx->out;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+}
+
+static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct g2d_ctx *ctx = vb2_get_drv_priv(vq);
+       struct g2d_frame *f = get_frame(ctx, vq->type);
+
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+
+       sizes[0] = f->size;
+       *nplanes = 1;
+       alloc_ctxs[0] = ctx->dev->alloc_ctx;
+
+       if (*nbuffers == 0)
+               *nbuffers = 1;
+
+       return 0;
+}
+
+static int g2d_buf_prepare(struct vb2_buffer *vb)
+{
+       struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type);
+
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+       vb2_set_plane_payload(vb, 0, f->size);
+       return 0;
+}
+
+static void g2d_buf_queue(struct vb2_buffer *vb)
+{
+       struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+
+static struct vb2_ops g2d_qops = {
+       .queue_setup    = g2d_queue_setup,
+       .buf_prepare    = g2d_buf_prepare,
+       .buf_queue      = g2d_buf_queue,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                                               struct vb2_queue *dst_vq)
+{
+       struct g2d_ctx *ctx = priv;
+       int ret;
+
+       memset(src_vq, 0, sizeof(*src_vq));
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->ops = &g2d_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       memset(dst_vq, 0, sizeof(*dst_vq));
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->ops = &g2d_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+       return vb2_queue_init(dst_vq);
+}
+
+static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx,
+                                                               ctrl_handler);
+       switch (ctrl->id) {
+       case V4L2_CID_COLORFX:
+               if (ctrl->val == V4L2_COLORFX_NEGATIVE)
+                       ctx->rop = ROP4_INVERT;
+               else
+                       ctx->rop = ROP4_COPY;
+       default:
+               v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops g2d_ctrl_ops = {
+       .s_ctrl         = g2d_s_ctrl,
+};
+
+int g2d_setup_ctrls(struct g2d_ctx *ctx)
+{
+       struct g2d_dev *dev = ctx->dev;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1);
+       if (ctx->ctrl_handler.error) {
+               v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+
+       v4l2_ctrl_new_std_menu(
+               &ctx->ctrl_handler,
+               &g2d_ctrl_ops,
+               V4L2_CID_COLORFX,
+               V4L2_COLORFX_NEGATIVE,
+               ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)),
+               V4L2_COLORFX_NONE);
+
+       if (ctx->ctrl_handler.error) {
+               v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+
+       return 0;
+}
+
+static int g2d_open(struct file *file)
+{
+       struct g2d_dev *dev = video_drvdata(file);
+       struct g2d_ctx *ctx = NULL;
+       int ret = 0;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->dev = dev;
+       /* Set default formats */
+       ctx->in         = def_frame;
+       ctx->out        = def_frame;
+
+       ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+       if (IS_ERR(ctx->m2m_ctx)) {
+               ret = PTR_ERR(ctx->m2m_ctx);
+               kfree(ctx);
+               return ret;
+       }
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+
+       g2d_setup_ctrls(ctx);
+
+       /* Write the default values to the ctx struct */
+       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+
+       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+
+       v4l2_info(&dev->v4l2_dev, "instance opened\n");
+       return 0;
+}
+
+static int g2d_release(struct file *file)
+{
+       struct g2d_dev *dev = video_drvdata(file);
+       struct g2d_ctx *ctx = fh2ctx(file->private_data);
+
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       v4l2_info(&dev->v4l2_dev, "instance closed\n");
+       return 0;
+}
+
+
+static int vidioc_querycap(struct file *file, void *priv,
+                               struct v4l2_capability *cap)
+{
+       strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
+       strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
+                                                       | V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
+{
+       struct g2d_fmt *fmt;
+       if (f->index >= NUM_FORMATS)
+               return -EINVAL;
+       fmt = &formats[f->index];
+       f->pixelformat = fmt->fourcc;
+       strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+       return 0;
+}
+
+static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+       struct g2d_ctx *ctx = prv;
+       struct vb2_queue *vq;
+       struct g2d_frame *frm;
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+       frm = get_frame(ctx, f->type);
+       if (IS_ERR(frm))
+               return PTR_ERR(frm);
+
+       f->fmt.pix.width                = frm->width;
+       f->fmt.pix.height               = frm->height;
+       f->fmt.pix.field                = V4L2_FIELD_NONE;
+       f->fmt.pix.pixelformat          = frm->fmt->fourcc;
+       f->fmt.pix.bytesperline         = (frm->width * frm->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage            = frm->size;
+       return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+       struct g2d_fmt *fmt;
+       enum v4l2_field *field;
+
+       fmt = find_fmt(f);
+       if (!fmt)
+               return -EINVAL;
+
+       field = &f->fmt.pix.field;
+       if (*field == V4L2_FIELD_ANY)
+               *field = V4L2_FIELD_NONE;
+       else if (*field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       if (f->fmt.pix.width > MAX_WIDTH)
+               f->fmt.pix.width = MAX_WIDTH;
+       if (f->fmt.pix.height > MAX_HEIGHT)
+               f->fmt.pix.height = MAX_HEIGHT;
+
+       if (f->fmt.pix.width < 1)
+               f->fmt.pix.width = 1;
+       if (f->fmt.pix.height < 1)
+               f->fmt.pix.height = 1;
+
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       struct vb2_queue *vq;
+       struct g2d_frame *frm;
+       struct g2d_fmt *fmt;
+       int ret = 0;
+
+       /* Adjust all values accordingly to the hardware capabilities
+        * and chosen format. */
+       ret = vidioc_try_fmt(file, prv, f);
+       if (ret)
+               return ret;
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type);
+               return -EBUSY;
+       }
+       frm = get_frame(ctx, f->type);
+       if (IS_ERR(frm))
+               return PTR_ERR(frm);
+       fmt = find_fmt(f);
+       if (!fmt)
+               return -EINVAL;
+       frm->width      = f->fmt.pix.width;
+       frm->height     = f->fmt.pix.height;
+       frm->size       = f->fmt.pix.sizeimage;
+       /* Reset crop settings */
+       frm->o_width    = 0;
+       frm->o_height   = 0;
+       frm->c_width    = frm->width;
+       frm->c_height   = frm->height;
+       frm->right      = frm->width;
+       frm->bottom     = frm->height;
+       frm->fmt        = fmt;
+       frm->stride     = f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct g2d_ctx *ctx = fh2ctx(file->private_data);
+       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+}
+
+static int g2d_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct g2d_ctx *ctx = fh2ctx(file->private_data);
+       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                       struct v4l2_requestbuffers *reqbufs)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                       struct v4l2_buffer *buf)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct g2d_ctx *ctx = priv;
+       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+                                       struct v4l2_cropcap *cr)
+{
+       struct g2d_ctx *ctx = priv;
+       struct g2d_frame *f;
+
+       f = get_frame(ctx, cr->type);
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+
+       cr->bounds.left         = 0;
+       cr->bounds.top          = 0;
+       cr->bounds.width        = f->width;
+       cr->bounds.height       = f->height;
+       cr->defrect             = cr->bounds;
+       return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_frame *f;
+
+       f = get_frame(ctx, cr->type);
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+
+       cr->c.left      = f->o_height;
+       cr->c.top       = f->o_width;
+       cr->c.width     = f->c_width;
+       cr->c.height    = f->c_height;
+       return 0;
+}
+
+static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       struct g2d_frame *f;
+
+       f = get_frame(ctx, cr->type);
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+
+       if (cr->c.top < 0 || cr->c.left < 0) {
+               v4l2_err(&dev->v4l2_dev,
+                       "doesn't support negative values for top & left\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_frame *f;
+       int ret;
+
+       ret = vidioc_try_crop(file, prv, cr);
+       if (ret)
+               return ret;
+       f = get_frame(ctx, cr->type);
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+
+       f->c_width      = cr->c.width;
+       f->c_height     = cr->c.height;
+       f->o_width      = cr->c.left;
+       f->o_height     = cr->c.top;
+       f->bottom       = f->o_height + f->c_height;
+       f->right        = f->o_width + f->c_width;
+       return 0;
+}
+
+static void g2d_lock(void *prv)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       mutex_lock(&dev->mutex);
+}
+
+static void g2d_unlock(void *prv)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       mutex_unlock(&dev->mutex);
+}
+
+static void job_abort(void *prv)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       int ret;
+
+       if (dev->curr == 0) /* No job currently running */
+               return;
+
+       ret = wait_event_timeout(dev->irq_queue,
+               dev->curr == 0,
+               msecs_to_jiffies(G2D_TIMEOUT));
+}
+
+static void device_run(void *prv)
+{
+       struct g2d_ctx *ctx = prv;
+       struct g2d_dev *dev = ctx->dev;
+       struct vb2_buffer *src, *dst;
+       u32 cmd = 0;
+
+       dev->curr = ctx;
+
+       src = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+
+       clk_enable(dev->gate);
+       g2d_reset(dev);
+
+       g2d_set_src_size(dev, &ctx->in);
+       g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0));
+
+       g2d_set_dst_size(dev, &ctx->out);
+       g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0));
+
+       g2d_set_rop4(dev, ctx->rop);
+       if (ctx->in.c_width != ctx->out.c_width ||
+               ctx->in.c_height != ctx->out.c_height)
+               cmd |= g2d_cmd_stretch(1);
+       g2d_set_cmd(dev, cmd);
+       g2d_start(dev);
+}
+
+static irqreturn_t g2d_isr(int irq, void *prv)
+{
+       struct g2d_dev *dev = prv;
+       struct g2d_ctx *ctx = dev->curr;
+       struct vb2_buffer *src, *dst;
+
+       g2d_clear_int(dev);
+       clk_disable(dev->gate);
+
+       BUG_ON(ctx == 0);
+
+       src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+       dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+       BUG_ON(src == 0);
+       BUG_ON(dst == 0);
+
+       v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
+       v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
+
+       dev->curr = 0;
+       wake_up(&dev->irq_queue);
+       return IRQ_HANDLED;
+}
+
+static const struct v4l2_file_operations g2d_fops = {
+       .owner          = THIS_MODULE,
+       .open           = g2d_open,
+       .release        = g2d_release,
+       .poll           = g2d_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = g2d_mmap,
+};
+
+static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+
+       .vidioc_enum_fmt_vid_cap        = vidioc_enum_fmt,
+       .vidioc_g_fmt_vid_cap           = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap         = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap           = vidioc_s_fmt,
+
+       .vidioc_enum_fmt_vid_out        = vidioc_enum_fmt,
+       .vidioc_g_fmt_vid_out           = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_out         = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_out           = vidioc_s_fmt,
+
+       .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_g_crop                  = vidioc_g_crop,
+       .vidioc_s_crop                  = vidioc_s_crop,
+       .vidioc_cropcap                 = vidioc_cropcap,
+};
+
+static struct video_device g2d_videodev = {
+       .name           = G2D_NAME,
+       .fops           = &g2d_fops,
+       .ioctl_ops      = &g2d_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release,
+};
+
+static struct v4l2_m2m_ops g2d_m2m_ops = {
+       .device_run     = device_run,
+       .job_abort      = job_abort,
+       .lock           = g2d_lock,
+       .unlock         = g2d_unlock,
+};
+
+static int g2d_probe(struct platform_device *pdev)
+{
+       struct g2d_dev *dev;
+       struct video_device *vfd;
+       struct resource *res;
+       int ret = 0;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+       spin_lock_init(&dev->irqlock);
+       mutex_init(&dev->mutex);
+       atomic_set(&dev->num_inst, 0);
+       init_waitqueue_head(&dev->irq_queue);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to find registers\n");
+               ret = -ENOENT;
+               goto free_dev;
+       }
+
+       dev->res_regs = request_mem_region(res->start, resource_size(res),
+                                               dev_name(&pdev->dev));
+
+       if (!dev->res_regs) {
+               dev_err(&pdev->dev, "failed to obtain register region\n");
+               ret = -ENOENT;
+               goto free_dev;
+       }
+
+       dev->regs = ioremap(res->start, resource_size(res));
+       if (!dev->regs) {
+               dev_err(&pdev->dev, "failed to map registers\n");
+               ret = -ENOENT;
+               goto rel_res_regs;
+       }
+
+       dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
+       if (IS_ERR_OR_NULL(dev->clk)) {
+               dev_err(&pdev->dev, "failed to get g2d clock\n");
+               ret = -ENXIO;
+               goto unmap_regs;
+       }
+
+       dev->gate = clk_get(&pdev->dev, "fimg2d");
+       if (IS_ERR_OR_NULL(dev->gate)) {
+               dev_err(&pdev->dev, "failed to get g2d clock gate\n");
+               ret = -ENXIO;
+               goto put_clk;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to find IRQ\n");
+               ret = -ENXIO;
+               goto put_clk_gate;
+       }
+
+       dev->irq = res->start;
+
+       ret = request_irq(dev->irq, g2d_isr, 0, pdev->name, dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to install IRQ\n");
+               goto put_clk_gate;
+       }
+
+       dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(dev->alloc_ctx)) {
+               ret = PTR_ERR(dev->alloc_ctx);
+               goto rel_irq;
+       }
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               goto alloc_ctx_cleanup;
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto unreg_v4l2_dev;
+       }
+       *vfd = g2d_videodev;
+       vfd->lock = &dev->mutex;
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               goto rel_vdev;
+       }
+       video_set_drvdata(vfd, dev);
+       snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
+       dev->vfd = vfd;
+       v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
+                                                               vfd->num);
+       platform_set_drvdata(pdev, dev);
+       dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
+       if (IS_ERR(dev->m2m_dev)) {
+               v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(dev->m2m_dev);
+               goto unreg_video_dev;
+       }
+
+       def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
+
+       return 0;
+
+unreg_video_dev:
+       video_unregister_device(dev->vfd);
+rel_vdev:
+       video_device_release(vfd);
+unreg_v4l2_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+alloc_ctx_cleanup:
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+rel_irq:
+       free_irq(dev->irq, dev);
+put_clk_gate:
+       clk_put(dev->gate);
+put_clk:
+       clk_put(dev->clk);
+unmap_regs:
+       iounmap(dev->regs);
+rel_res_regs:
+       release_resource(dev->res_regs);
+free_dev:
+       kfree(dev);
+       return ret;
+}
+
+static int g2d_remove(struct platform_device *pdev)
+{
+       struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev);
+
+       v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
+       v4l2_m2m_release(dev->m2m_dev);
+       video_unregister_device(dev->vfd);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+       free_irq(dev->irq, dev);
+       clk_put(dev->gate);
+       clk_put(dev->clk);
+       iounmap(dev->regs);
+       release_resource(dev->res_regs);
+       kfree(dev);
+       return 0;
+}
+
+static struct platform_driver g2d_pdrv = {
+       .probe          = g2d_probe,
+       .remove         = g2d_remove,
+       .driver         = {
+               .name = G2D_NAME,
+               .owner = THIS_MODULE,
+       },
+};
+
+module_platform_driver(g2d_pdrv);
+
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/video/s5p-g2d/g2d.h
new file mode 100644 (file)
index 0000000..5eae901
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version
+ */
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define G2D_NAME "s5p-g2d"
+
+struct g2d_dev {
+       struct v4l2_device      v4l2_dev;
+       struct v4l2_m2m_dev     *m2m_dev;
+       struct video_device     *vfd;
+       struct mutex            mutex;
+       spinlock_t              irqlock;
+       atomic_t                num_inst;
+       struct vb2_alloc_ctx    *alloc_ctx;
+       struct resource         *res_regs;
+       void __iomem            *regs;
+       struct clk              *clk;
+       struct clk              *gate;
+       struct g2d_ctx          *curr;
+       int irq;
+       wait_queue_head_t       irq_queue;
+};
+
+struct g2d_frame {
+       /* Original dimensions */
+       u32     width;
+       u32     height;
+       /* Crop size */
+       u32     c_width;
+       u32     c_height;
+       /* Offset */
+       u32     o_width;
+       u32     o_height;
+       /* Image format */
+       struct g2d_fmt *fmt;
+       /* Variables that can calculated once and reused */
+       u32     stride;
+       u32     bottom;
+       u32     right;
+       u32     size;
+};
+
+struct g2d_ctx {
+       struct v4l2_fh fh;
+       struct g2d_dev          *dev;
+       struct v4l2_m2m_ctx     *m2m_ctx;
+       struct g2d_frame        in;
+       struct g2d_frame        out;
+       struct v4l2_ctrl_handler ctrl_handler;
+       u32 rop;
+};
+
+struct g2d_fmt {
+       char    *name;
+       u32     fourcc;
+       int     depth;
+       u32     hw;
+};
+
+
+void g2d_reset(struct g2d_dev *d);
+void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f);
+void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a);
+void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f);
+void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a);
+void g2d_start(struct g2d_dev *d);
+void g2d_clear_int(struct g2d_dev *d);
+void g2d_set_rop4(struct g2d_dev *d, u32 r);
+u32 g2d_cmd_stretch(u32 e);
+void g2d_set_cmd(struct g2d_dev *d, u32 c);
+
+
diff --git a/drivers/media/video/s5p-jpeg/Makefile b/drivers/media/video/s5p-jpeg/Makefile
new file mode 100644 (file)
index 0000000..ddc2900
--- /dev/null
@@ -0,0 +1,2 @@
+s5p-jpeg-objs := jpeg-core.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) := s5p-jpeg.o
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
new file mode 100644 (file)
index 0000000..f841a3e
--- /dev/null
@@ -0,0 +1,1481 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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/clk.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw.h"
+
+static struct s5p_jpeg_fmt formats_enc[] = {
+       {
+               .name           = "YUV 4:2:0 planar, YCbCr",
+               .fourcc         = V4L2_PIX_FMT_YUV420,
+               .depth          = 12,
+               .colplanes      = 3,
+               .types          = MEM2MEM_CAPTURE,
+       },
+       {
+               .name           = "YUV 4:2:2 packed, YCbYCr",
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .depth          = 16,
+               .colplanes      = 1,
+               .types          = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       },
+       {
+               .name           = "RGB565",
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .depth          = 16,
+               .colplanes      = 1,
+               .types          = MEM2MEM_OUTPUT,
+       },
+};
+#define NUM_FORMATS_ENC ARRAY_SIZE(formats_enc)
+
+static struct s5p_jpeg_fmt formats_dec[] = {
+       {
+               .name           = "YUV 4:2:0 planar, YCbCr",
+               .fourcc         = V4L2_PIX_FMT_YUV420,
+               .depth          = 12,
+               .colplanes      = 3,
+               .h_align        = 4,
+               .v_align        = 4,
+               .types          = MEM2MEM_CAPTURE,
+       },
+       {
+               .name           = "YUV 4:2:2 packed, YCbYCr",
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 4,
+               .v_align        = 3,
+               .types          = MEM2MEM_CAPTURE,
+       },
+       {
+               .name           = "JPEG JFIF",
+               .fourcc         = V4L2_PIX_FMT_JPEG,
+               .colplanes      = 1,
+               .types          = MEM2MEM_OUTPUT,
+       },
+};
+#define NUM_FORMATS_DEC ARRAY_SIZE(formats_dec)
+
+static const unsigned char qtbl_luminance[4][64] = {
+       {/* level 1 - high quality */
+                8,  6,  6,  8, 12, 14, 16, 17,
+                6,  6,  6,  8, 10, 13, 12, 15,
+                6,  6,  7,  8, 13, 14, 18, 24,
+                8,  8,  8, 14, 13, 19, 24, 35,
+               12, 10, 13, 13, 20, 26, 34, 39,
+               14, 13, 14, 19, 26, 34, 39, 39,
+               16, 12, 18, 24, 34, 39, 39, 39,
+               17, 15, 24, 35, 39, 39, 39, 39
+       },
+       {/* level 2 */
+               12,  8,  8, 12, 17, 21, 24, 23,
+                8,  9,  9, 11, 15, 19, 18, 23,
+                8,  9, 10, 12, 19, 20, 27, 36,
+               12, 11, 12, 21, 20, 28, 36, 53,
+               17, 15, 19, 20, 30, 39, 51, 59,
+               21, 19, 20, 28, 39, 51, 59, 59,
+               24, 18, 27, 36, 51, 59, 59, 59,
+               23, 23, 36, 53, 59, 59, 59, 59
+       },
+       {/* level 3 */
+               16, 11, 11, 16, 23, 27, 31, 30,
+               11, 12, 12, 15, 20, 23, 23, 30,
+               11, 12, 13, 16, 23, 26, 35, 47,
+               16, 15, 16, 23, 26, 37, 47, 64,
+               23, 20, 23, 26, 39, 51, 64, 64,
+               27, 23, 26, 37, 51, 64, 64, 64,
+               31, 23, 35, 47, 64, 64, 64, 64,
+               30, 30, 47, 64, 64, 64, 64, 64
+       },
+       {/*level 4 - low quality */
+               20, 16, 25, 39, 50, 46, 62, 68,
+               16, 18, 23, 38, 38, 53, 65, 68,
+               25, 23, 31, 38, 53, 65, 68, 68,
+               39, 38, 38, 53, 65, 68, 68, 68,
+               50, 38, 53, 65, 68, 68, 68, 68,
+               46, 53, 65, 68, 68, 68, 68, 68,
+               62, 65, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68
+       }
+};
+
+static const unsigned char qtbl_chrominance[4][64] = {
+       {/* level 1 - high quality */
+                9,  8,  9, 11, 14, 17, 19, 24,
+                8, 10,  9, 11, 14, 13, 17, 22,
+                9,  9, 13, 14, 13, 15, 23, 26,
+               11, 11, 14, 14, 15, 20, 26, 33,
+               14, 14, 13, 15, 20, 24, 33, 39,
+               17, 13, 15, 20, 24, 32, 39, 39,
+               19, 17, 23, 26, 33, 39, 39, 39,
+               24, 22, 26, 33, 39, 39, 39, 39
+       },
+       {/* level 2 */
+               13, 11, 13, 16, 20, 20, 29, 37,
+               11, 14, 14, 14, 16, 20, 26, 32,
+               13, 14, 15, 17, 20, 23, 35, 40,
+               16, 14, 17, 21, 23, 30, 40, 50,
+               20, 16, 20, 23, 30, 37, 50, 59,
+               20, 20, 23, 30, 37, 48, 59, 59,
+               29, 26, 35, 40, 50, 59, 59, 59,
+               37, 32, 40, 50, 59, 59, 59, 59
+       },
+       {/* level 3 */
+               17, 15, 17, 21, 20, 26, 38, 48,
+               15, 19, 18, 17, 20, 26, 35, 43,
+               17, 18, 20, 22, 26, 30, 46, 53,
+               21, 17, 22, 28, 30, 39, 53, 64,
+               20, 20, 26, 30, 39, 48, 64, 64,
+               26, 26, 30, 39, 48, 63, 64, 64,
+               38, 35, 46, 53, 64, 64, 64, 64,
+               48, 43, 53, 64, 64, 64, 64, 64
+       },
+       {/*level 4 - low quality */
+               21, 25, 32, 38, 54, 68, 68, 68,
+               25, 28, 24, 38, 54, 68, 68, 68,
+               32, 24, 32, 43, 66, 68, 68, 68,
+               38, 38, 43, 53, 68, 68, 68, 68,
+               54, 54, 66, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68
+       }
+};
+
+static const unsigned char hdctbl0[16] = {
+       0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char hdctblg0[12] = {
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+static const unsigned char hactbl0[16] = {
+       0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+static const unsigned char hactblg0[162] = {
+       0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+       0xf9, 0xfa
+};
+
+static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl,
+                  unsigned long tab, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_qtbl_lum(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 0 with data for luma */
+       jpeg_set_qtbl(regs, qtbl_luminance[quality], S5P_JPG_QTBL_CONTENT(0),
+                     ARRAY_SIZE(qtbl_luminance[quality]));
+}
+
+static inline void jpeg_set_qtbl_chr(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 1 with data for chroma */
+       jpeg_set_qtbl(regs, qtbl_chrominance[quality], S5P_JPG_QTBL_CONTENT(1),
+                     ARRAY_SIZE(qtbl_chrominance[quality]));
+}
+
+static inline void jpeg_set_htbl(void __iomem *regs, const unsigned char *htbl,
+                  unsigned long tab, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_hdctbl(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0), ARRAY_SIZE(hdctbl0));
+}
+
+static inline void jpeg_set_hdctblg(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0), ARRAY_SIZE(hdctblg0));
+}
+
+static inline void jpeg_set_hactbl(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0), ARRAY_SIZE(hactbl0));
+}
+
+static inline void jpeg_set_hactblg(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0), ARRAY_SIZE(hactblg0));
+}
+
+/*
+ * ============================================================================
+ * Device file operations
+ * ============================================================================
+ */
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq);
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode,
+                                                __u32 pixelformat);
+
+static int s5p_jpeg_open(struct file *file)
+{
+       struct s5p_jpeg *jpeg = video_drvdata(file);
+       struct video_device *vfd = video_devdata(file);
+       struct s5p_jpeg_ctx *ctx;
+       struct s5p_jpeg_fmt *out_fmt;
+
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       file->private_data = ctx;
+       ctx->jpeg = jpeg;
+       if (vfd == jpeg->vfd_encoder) {
+               ctx->mode = S5P_JPEG_ENCODE;
+               out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_RGB565);
+       } else {
+               ctx->mode = S5P_JPEG_DECODE;
+               out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG);
+       }
+
+       ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
+       if (IS_ERR(ctx->m2m_ctx)) {
+               int err = PTR_ERR(ctx->m2m_ctx);
+               kfree(ctx);
+               return err;
+       }
+
+       ctx->out_q.fmt = out_fmt;
+       ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV);
+
+       return 0;
+}
+
+static int s5p_jpeg_release(struct file *file)
+{
+       struct s5p_jpeg_ctx *ctx = file->private_data;
+
+       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       kfree(ctx);
+
+       return 0;
+}
+
+static unsigned int s5p_jpeg_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct s5p_jpeg_ctx *ctx = file->private_data;
+
+       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+}
+
+static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct s5p_jpeg_ctx *ctx = file->private_data;
+
+       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations s5p_jpeg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = s5p_jpeg_open,
+       .release        = s5p_jpeg_release,
+       .poll           = s5p_jpeg_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = s5p_jpeg_mmap,
+};
+
+/*
+ * ============================================================================
+ * video ioctl operations
+ * ============================================================================
+ */
+
+static int get_byte(struct s5p_jpeg_buffer *buf)
+{
+       if (buf->curr >= buf->size)
+               return -1;
+
+       return ((unsigned char *)buf->data)[buf->curr++];
+}
+
+static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
+{
+       unsigned int temp;
+       int byte;
+
+       byte = get_byte(buf);
+       if (byte == -1)
+               return -1;
+       temp = byte << 8;
+       byte = get_byte(buf);
+       if (byte == -1)
+               return -1;
+       *word = (unsigned int)byte | temp;
+       return 0;
+}
+
+static void skip(struct s5p_jpeg_buffer *buf, long len)
+{
+       if (len <= 0)
+               return;
+
+       while (len--)
+               get_byte(buf);
+}
+
+static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
+                              unsigned long buffer, unsigned long size)
+{
+       int c, components, notfound;
+       unsigned int height, width, word;
+       long length;
+       struct s5p_jpeg_buffer jpeg_buffer;
+
+       jpeg_buffer.size = size;
+       jpeg_buffer.data = buffer;
+       jpeg_buffer.curr = 0;
+
+       notfound = 1;
+       while (notfound) {
+               c = get_byte(&jpeg_buffer);
+               if (c == -1)
+                       break;
+               if (c != 0xff)
+                       continue;
+               do
+                       c = get_byte(&jpeg_buffer);
+               while (c == 0xff);
+               if (c == -1)
+                       break;
+               if (c == 0)
+                       continue;
+               length = 0;
+               switch (c) {
+               /* SOF0: baseline JPEG */
+               case SOF0:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       if (get_byte(&jpeg_buffer) == -1)
+                               break;
+                       if (get_word_be(&jpeg_buffer, &height))
+                               break;
+                       if (get_word_be(&jpeg_buffer, &width))
+                               break;
+                       components = get_byte(&jpeg_buffer);
+                       if (components == -1)
+                               break;
+                       notfound = 0;
+
+                       skip(&jpeg_buffer, components * 3);
+                       break;
+
+               /* skip payload-less markers */
+               case RST ... RST + 7:
+               case SOI:
+               case EOI:
+               case TEM:
+                       break;
+
+               /* skip uninteresting payload markers */
+               default:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       length = (long)word - 2;
+                       skip(&jpeg_buffer, length);
+                       break;
+               }
+       }
+       result->w = width;
+       result->h = height;
+       result->size = components;
+       return !notfound;
+}
+
+static int s5p_jpeg_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder",
+                       sizeof(cap->driver));
+               strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
+                       sizeof(cap->card));
+       } else {
+               strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder",
+                       sizeof(cap->driver));
+               strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
+                       sizeof(cap->card));
+       }
+       cap->bus_info[0] = 0;
+       cap->capabilities = V4L2_CAP_STREAMING |
+                           V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_VIDEO_OUTPUT;
+       return 0;
+}
+
+static int enum_fmt(struct s5p_jpeg_fmt *formats, int n,
+                   struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num = 0;
+
+       for (i = 0; i < n; ++i) {
+               if (formats[i].types & type) {
+                       /* index-th format of type type found ? */
+                       if (num == f->index)
+                               break;
+                       /* Correct type but haven't reached our index yet,
+                        * just increment per-type index */
+                       ++num;
+               }
+       }
+
+       /* Format not found */
+       if (i >= n)
+               return -EINVAL;
+
+       strlcpy(f->description, formats[i].name, sizeof(f->description));
+       f->pixelformat = formats[i].fourcc;
+
+       return 0;
+}
+
+static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct s5p_jpeg_ctx *ctx;
+
+       ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               return enum_fmt(formats_enc, NUM_FORMATS_ENC, f,
+                               MEM2MEM_CAPTURE);
+
+       return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_CAPTURE);
+}
+
+static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct s5p_jpeg_ctx *ctx;
+
+       ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               return enum_fmt(formats_enc, NUM_FORMATS_ENC, f,
+                               MEM2MEM_OUTPUT);
+
+       return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_OUTPUT);
+}
+
+static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
+                                         enum v4l2_buf_type type)
+{
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return &ctx->out_q;
+       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return &ctx->cap_q;
+
+       return NULL;
+}
+
+static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct s5p_jpeg_q_data *q_data = NULL;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct s5p_jpeg_ctx *ct = priv;
+
+       vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
+               return -EINVAL;
+       q_data = get_q_data(ct, f->type);
+       BUG_ON(q_data == NULL);
+
+       pix->width = q_data->w;
+       pix->height = q_data->h;
+       pix->field = V4L2_FIELD_NONE;
+       pix->pixelformat = q_data->fmt->fourcc;
+       pix->bytesperline = 0;
+       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
+               u32 bpl = q_data->w;
+               if (q_data->fmt->colplanes == 1)
+                       bpl = (bpl * q_data->fmt->depth) >> 3;
+               pix->bytesperline = bpl;
+       }
+       pix->sizeimage = q_data->size;
+
+       return 0;
+}
+
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode,
+                                                u32 pixelformat)
+{
+       unsigned int k;
+       struct s5p_jpeg_fmt *formats;
+       int n;
+
+       if (mode == S5P_JPEG_ENCODE) {
+               formats = formats_enc;
+               n = NUM_FORMATS_ENC;
+       } else {
+               formats = formats_dec;
+               n = NUM_FORMATS_DEC;
+       }
+
+       for (k = 0; k < n; k++) {
+               struct s5p_jpeg_fmt *fmt = &formats[k];
+               if (fmt->fourcc == pixelformat)
+                       return fmt;
+       }
+
+       return NULL;
+
+}
+
+static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+                                  unsigned int walign,
+                                  u32 *h, unsigned int hmin, unsigned int hmax,
+                                  unsigned int halign)
+{
+       int width, height, w_step, h_step;
+
+       width = *w;
+       height = *h;
+
+       w_step = 1 << walign;
+       h_step = 1 << halign;
+       v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
+
+       if (*w < width && (*w + w_step) < wmax)
+               *w += w_step;
+       if (*h < height && (*h + h_step) < hmax)
+               *h += h_step;
+
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
+                         struct s5p_jpeg_ctx *ctx, int q_type)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+
+       if (pix->field == V4L2_FIELD_ANY)
+               pix->field = V4L2_FIELD_NONE;
+       else if (pix->field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       /* V4L2 specification suggests the driver corrects the format struct
+        * if any of the dimensions is unsupported */
+       if (q_type == MEM2MEM_OUTPUT)
+               jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+                                      S5P_JPEG_MAX_WIDTH, 0,
+                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
+                                      S5P_JPEG_MAX_HEIGHT, 0);
+       else
+               jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+                                      S5P_JPEG_MAX_WIDTH, fmt->h_align,
+                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
+                                      S5P_JPEG_MAX_HEIGHT, fmt->v_align);
+
+       if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+               if (pix->sizeimage <= 0)
+                       pix->sizeimage = PAGE_SIZE;
+               pix->bytesperline = 0;
+       } else {
+               u32 bpl = pix->bytesperline;
+
+               if (fmt->colplanes > 1 && bpl < pix->width)
+                       bpl = pix->width; /* planar */
+
+               if (fmt->colplanes == 1 && /* packed */
+                   (bpl << 3) * fmt->depth < pix->width)
+                       bpl = (pix->width * fmt->depth) >> 3;
+
+               pix->bytesperline = bpl;
+               pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
+       }
+
+       return 0;
+}
+
+static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct s5p_jpeg_fmt *fmt;
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat);
+       if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
+               v4l2_err(&ctx->jpeg->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_CAPTURE);
+}
+
+static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct s5p_jpeg_fmt *fmt;
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat);
+       if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
+               v4l2_err(&ctx->jpeg->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_OUTPUT);
+}
+
+static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct s5p_jpeg_q_data *q_data = NULL;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+
+       vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ct, f->type);
+       BUG_ON(q_data == NULL);
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       q_data->fmt = s5p_jpeg_find_format(ct->mode, pix->pixelformat);
+       q_data->w = pix->width;
+       q_data->h = pix->height;
+       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)
+               q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
+       else
+               q_data->size = pix->sizeimage;
+
+       return 0;
+}
+
+static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return s5p_jpeg_s_fmt(priv, f);
+}
+
+static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       return s5p_jpeg_s_fmt(priv, f);
+}
+
+static int s5p_jpeg_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int s5p_jpeg_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *buf)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_dqbuf(struct file *file, void *priv,
+                         struct v4l2_buffer *buf)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int s5p_jpeg_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+int s5p_jpeg_g_selection(struct file *file, void *priv,
+                        struct v4l2_selection *s)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* For JPEG blob active == default == bounds */
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP_ACTIVE:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               s->r.width = ctx->out_q.w;
+               s->r.height = ctx->out_q.h;
+               break;
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_PADDED:
+               s->r.width = ctx->cap_q.w;
+               s->r.height = ctx->cap_q.h;
+               break;
+       default:
+               return -EINVAL;
+       }
+       s->r.left = 0;
+       s->r.top = 0;
+       return 0;
+}
+
+static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv,
+                              struct v4l2_jpegcompression *compr)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_DECODE)
+               return -ENOTTY;
+
+       memset(compr, 0, sizeof(*compr));
+       compr->quality = ctx->compr_quality;
+
+       return 0;
+}
+
+static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv,
+                              struct v4l2_jpegcompression *compr)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_DECODE)
+               return -ENOTTY;
+
+       compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST,
+                              S5P_JPEG_COMPR_QUAL_WORST);
+
+       ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality;
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
+       .vidioc_querycap                = s5p_jpeg_querycap,
+
+       .vidioc_enum_fmt_vid_cap        = s5p_jpeg_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out        = s5p_jpeg_enum_fmt_vid_out,
+
+       .vidioc_g_fmt_vid_cap           = s5p_jpeg_g_fmt,
+       .vidioc_g_fmt_vid_out           = s5p_jpeg_g_fmt,
+
+       .vidioc_try_fmt_vid_cap         = s5p_jpeg_try_fmt_vid_cap,
+       .vidioc_try_fmt_vid_out         = s5p_jpeg_try_fmt_vid_out,
+
+       .vidioc_s_fmt_vid_cap           = s5p_jpeg_s_fmt_vid_cap,
+       .vidioc_s_fmt_vid_out           = s5p_jpeg_s_fmt_vid_out,
+
+       .vidioc_reqbufs                 = s5p_jpeg_reqbufs,
+       .vidioc_querybuf                = s5p_jpeg_querybuf,
+
+       .vidioc_qbuf                    = s5p_jpeg_qbuf,
+       .vidioc_dqbuf                   = s5p_jpeg_dqbuf,
+
+       .vidioc_streamon                = s5p_jpeg_streamon,
+       .vidioc_streamoff               = s5p_jpeg_streamoff,
+
+       .vidioc_g_selection             = s5p_jpeg_g_selection,
+
+       .vidioc_g_jpegcomp              = s5p_jpeg_g_jpegcomp,
+       .vidioc_s_jpegcomp              = s5p_jpeg_s_jpegcomp,
+};
+
+/*
+ * ============================================================================
+ * mem2mem callbacks
+ * ============================================================================
+ */
+
+static void s5p_jpeg_device_run(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_buffer *src_buf, *dst_buf;
+       unsigned long src_addr, dst_addr;
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+       dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+
+       jpeg_reset(jpeg->regs);
+       jpeg_poweron(jpeg->regs);
+       jpeg_proc_mode(jpeg->regs, ctx->mode);
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
+                       jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565);
+               else
+                       jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422);
+               if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
+                       jpeg_subsampling_mode(jpeg->regs,
+                                             S5P_JPEG_SUBSAMPLING_422);
+               else
+                       jpeg_subsampling_mode(jpeg->regs,
+                                             S5P_JPEG_SUBSAMPLING_420);
+               jpeg_dri(jpeg->regs, 0);
+               jpeg_x(jpeg->regs, ctx->out_q.w);
+               jpeg_y(jpeg->regs, ctx->out_q.h);
+               jpeg_imgadr(jpeg->regs, src_addr);
+               jpeg_jpgadr(jpeg->regs, dst_addr);
+
+               /* ultimately comes from sizeimage from userspace */
+               jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
+
+               /* JPEG RGB to YCbCr conversion matrix */
+               jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
+               jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
+               jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
+               jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
+               jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
+               jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
+               jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
+               jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
+               jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
+
+               /*
+                * JPEG IP allows storing 4 quantization tables
+                * We fill table 0 for luma and table 1 for chroma
+                */
+               jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+               jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+               /* use table 0 for Y */
+               jpeg_qtbl(jpeg->regs, 1, 0);
+               /* use table 1 for Cb and Cr*/
+               jpeg_qtbl(jpeg->regs, 2, 1);
+               jpeg_qtbl(jpeg->regs, 3, 1);
+
+               /* Y, Cb, Cr use Huffman table 0 */
+               jpeg_htbl_ac(jpeg->regs, 1);
+               jpeg_htbl_dc(jpeg->regs, 1);
+               jpeg_htbl_ac(jpeg->regs, 2);
+               jpeg_htbl_dc(jpeg->regs, 2);
+               jpeg_htbl_ac(jpeg->regs, 3);
+               jpeg_htbl_dc(jpeg->regs, 3);
+       } else {
+               jpeg_rst_int_enable(jpeg->regs, true);
+               jpeg_data_num_int_enable(jpeg->regs, true);
+               jpeg_final_mcu_num_int_enable(jpeg->regs, true);
+               jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
+               jpeg_jpgadr(jpeg->regs, src_addr);
+               jpeg_imgadr(jpeg->regs, dst_addr);
+       }
+       jpeg_start(jpeg->regs);
+}
+
+static int s5p_jpeg_job_ready(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_DECODE)
+               return ctx->hdr_parsed;
+       return 1;
+}
+
+static void s5p_jpeg_job_abort(void *priv)
+{
+}
+
+static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
+       .device_run     = s5p_jpeg_device_run,
+       .job_ready      = s5p_jpeg_job_ready,
+       .job_abort      = s5p_jpeg_job_abort,
+};
+
+/*
+ * ============================================================================
+ * Queue operations
+ * ============================================================================
+ */
+
+static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+                               unsigned int *nplanes, unsigned int sizes[],
+                               void *alloc_ctxs[])
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+       struct s5p_jpeg_q_data *q_data = NULL;
+       unsigned int size, count = *nbuffers;
+
+       q_data = get_q_data(ctx, vq->type);
+       BUG_ON(q_data == NULL);
+
+       size = q_data->size;
+
+       /*
+        * header is parsed during decoding and parsed information stored
+        * in the context so we do not allow another buffer to overwrite it
+        */
+       if (ctx->mode == S5P_JPEG_DECODE)
+               count = 1;
+
+       *nbuffers = count;
+       *nplanes = 1;
+       sizes[0] = size;
+       alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
+
+       return 0;
+}
+
+static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct s5p_jpeg_q_data *q_data = NULL;
+
+       q_data = get_q_data(ctx, vb->vb2_queue->type);
+       BUG_ON(q_data == NULL);
+
+       if (vb2_plane_size(vb, 0) < q_data->size) {
+               pr_err("%s data will not fit into plane (%lu < %lu)\n",
+                               __func__, vb2_plane_size(vb, 0),
+                               (long)q_data->size);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->size);
+
+       return 0;
+}
+
+static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+       if (ctx->mode == S5P_JPEG_DECODE &&
+           vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               struct s5p_jpeg_q_data tmp, *q_data;
+               ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
+                    (unsigned long)vb2_plane_vaddr(vb, 0),
+                    min((unsigned long)ctx->out_q.size,
+                        vb2_get_plane_payload(vb, 0)));
+               if (!ctx->hdr_parsed) {
+                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+                       return;
+               }
+
+               q_data = &ctx->out_q;
+               q_data->w = tmp.w;
+               q_data->h = tmp.h;
+
+               q_data = &ctx->cap_q;
+               q_data->w = tmp.w;
+               q_data->h = tmp.h;
+
+               jpeg_bound_align_image(&q_data->w, S5P_JPEG_MIN_WIDTH,
+                                      S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,
+                                      &q_data->h, S5P_JPEG_MIN_HEIGHT,
+                                      S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align
+                                     );
+               q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
+       }
+       if (ctx->m2m_ctx)
+               v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+static void s5p_jpeg_wait_prepare(struct vb2_queue *vq)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+
+       mutex_unlock(&ctx->jpeg->lock);
+}
+
+static void s5p_jpeg_wait_finish(struct vb2_queue *vq)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+
+       mutex_lock(&ctx->jpeg->lock);
+}
+
+static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+       int ret;
+
+       ret = pm_runtime_get_sync(ctx->jpeg->dev);
+
+       return ret > 0 ? 0 : ret;
+}
+
+static int s5p_jpeg_stop_streaming(struct vb2_queue *q)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+
+       pm_runtime_put(ctx->jpeg->dev);
+
+       return 0;
+}
+
+static struct vb2_ops s5p_jpeg_qops = {
+       .queue_setup            = s5p_jpeg_queue_setup,
+       .buf_prepare            = s5p_jpeg_buf_prepare,
+       .buf_queue              = s5p_jpeg_buf_queue,
+       .wait_prepare           = s5p_jpeg_wait_prepare,
+       .wait_finish            = s5p_jpeg_wait_finish,
+       .start_streaming        = s5p_jpeg_start_streaming,
+       .stop_streaming         = s5p_jpeg_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       int ret;
+
+       memset(src_vq, 0, sizeof(*src_vq));
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &s5p_jpeg_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       memset(dst_vq, 0, sizeof(*dst_vq));
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &s5p_jpeg_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/*
+ * ============================================================================
+ * ISR
+ * ============================================================================
+ */
+
+static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
+{
+       struct s5p_jpeg *jpeg = dev_id;
+       struct s5p_jpeg_ctx *curr_ctx;
+       struct vb2_buffer *src_buf, *dst_buf;
+       unsigned long payload_size = 0;
+       enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+       bool enc_jpeg_too_large = false;
+       bool timer_elapsed = false;
+       bool op_completed = false;
+
+       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
+       if (curr_ctx->mode == S5P_JPEG_ENCODE)
+               enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs);
+       timer_elapsed = jpeg_timer_stat(jpeg->regs);
+       op_completed = jpeg_result_stat_ok(jpeg->regs);
+       if (curr_ctx->mode == S5P_JPEG_DECODE)
+               op_completed = op_completed && jpeg_stream_stat_ok(jpeg->regs);
+
+       if (enc_jpeg_too_large) {
+               state = VB2_BUF_STATE_ERROR;
+               jpeg_clear_enc_stream_stat(jpeg->regs);
+       } else if (timer_elapsed) {
+               state = VB2_BUF_STATE_ERROR;
+               jpeg_clear_timer_stat(jpeg->regs);
+       } else if (!op_completed) {
+               state = VB2_BUF_STATE_ERROR;
+       } else {
+               payload_size = jpeg_compressed_size(jpeg->regs);
+       }
+
+       v4l2_m2m_buf_done(src_buf, state);
+       if (curr_ctx->mode == S5P_JPEG_ENCODE)
+               vb2_set_plane_payload(dst_buf, 0, payload_size);
+       v4l2_m2m_buf_done(dst_buf, state);
+       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
+
+       jpeg_clear_int(jpeg->regs);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * ============================================================================
+ * Driver basic infrastructure
+ * ============================================================================
+ */
+
+static int s5p_jpeg_probe(struct platform_device *pdev)
+{
+       struct s5p_jpeg *jpeg;
+       struct resource *res;
+       int ret;
+
+       /* JPEG IP abstraction struct */
+       jpeg = kzalloc(sizeof(struct s5p_jpeg), GFP_KERNEL);
+       if (!jpeg)
+               return -ENOMEM;
+
+       mutex_init(&jpeg->lock);
+       jpeg->dev = &pdev->dev;
+
+       /* memory-mapped registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "cannot find IO resource\n");
+               ret = -ENOENT;
+               goto jpeg_alloc_rollback;
+       }
+
+       jpeg->ioarea = request_mem_region(res->start, resource_size(res),
+                                         pdev->name);
+       if (!jpeg->ioarea) {
+               dev_err(&pdev->dev, "cannot request IO\n");
+               ret = -ENXIO;
+               goto jpeg_alloc_rollback;
+       }
+
+       jpeg->regs = ioremap(res->start, resource_size(res));
+       if (!jpeg->regs) {
+               dev_err(&pdev->dev, "cannot map IO\n");
+               ret = -ENXIO;
+               goto mem_region_rollback;
+       }
+
+       dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+               jpeg->regs, jpeg->ioarea, res);
+
+       /* interrupt service routine registration */
+       jpeg->irq = ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ\n");
+               goto ioremap_rollback;
+       }
+
+       ret = request_irq(jpeg->irq, s5p_jpeg_irq, 0,
+                         dev_name(&pdev->dev), jpeg);
+
+       if (ret) {
+               dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
+               goto ioremap_rollback;
+       }
+
+       /* clocks */
+       jpeg->clk = clk_get(&pdev->dev, "jpeg");
+       if (IS_ERR(jpeg->clk)) {
+               dev_err(&pdev->dev, "cannot get clock\n");
+               ret = PTR_ERR(jpeg->clk);
+               goto request_irq_rollback;
+       }
+       dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
+       clk_enable(jpeg->clk);
+
+       /* v4l2 device */
+       ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+               goto clk_get_rollback;
+       }
+
+       /* mem2mem device */
+       jpeg->m2m_dev = v4l2_m2m_init(&s5p_jpeg_m2m_ops);
+       if (IS_ERR(jpeg->m2m_dev)) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(jpeg->m2m_dev);
+               goto device_register_rollback;
+       }
+
+       jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(jpeg->alloc_ctx)) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
+               ret = PTR_ERR(jpeg->alloc_ctx);
+               goto m2m_init_rollback;
+       }
+
+       /* JPEG encoder /dev/videoX node */
+       jpeg->vfd_encoder = video_device_alloc();
+       if (!jpeg->vfd_encoder) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto vb2_allocator_rollback;
+       }
+       strlcpy(jpeg->vfd_encoder->name, S5P_JPEG_M2M_NAME,
+               sizeof(jpeg->vfd_encoder->name));
+       jpeg->vfd_encoder->fops         = &s5p_jpeg_fops;
+       jpeg->vfd_encoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
+       jpeg->vfd_encoder->minor        = -1;
+       jpeg->vfd_encoder->release      = video_device_release;
+       jpeg->vfd_encoder->lock         = &jpeg->lock;
+       jpeg->vfd_encoder->v4l2_dev     = &jpeg->v4l2_dev;
+
+       ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
+       if (ret) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+               goto enc_vdev_alloc_rollback;
+       }
+
+       video_set_drvdata(jpeg->vfd_encoder, jpeg);
+       v4l2_info(&jpeg->v4l2_dev,
+                 "encoder device registered as /dev/video%d\n",
+                 jpeg->vfd_encoder->num);
+
+       /* JPEG decoder /dev/videoX node */
+       jpeg->vfd_decoder = video_device_alloc();
+       if (!jpeg->vfd_decoder) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto enc_vdev_register_rollback;
+       }
+       strlcpy(jpeg->vfd_decoder->name, S5P_JPEG_M2M_NAME,
+               sizeof(jpeg->vfd_decoder->name));
+       jpeg->vfd_decoder->fops         = &s5p_jpeg_fops;
+       jpeg->vfd_decoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
+       jpeg->vfd_decoder->minor        = -1;
+       jpeg->vfd_decoder->release      = video_device_release;
+       jpeg->vfd_decoder->lock         = &jpeg->lock;
+       jpeg->vfd_decoder->v4l2_dev     = &jpeg->v4l2_dev;
+
+       ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
+       if (ret) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+               goto dec_vdev_alloc_rollback;
+       }
+
+       video_set_drvdata(jpeg->vfd_decoder, jpeg);
+       v4l2_info(&jpeg->v4l2_dev,
+                 "decoder device registered as /dev/video%d\n",
+                 jpeg->vfd_decoder->num);
+
+       /* final statements & power management */
+       platform_set_drvdata(pdev, jpeg);
+
+       pm_runtime_enable(&pdev->dev);
+
+       v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
+
+       return 0;
+
+dec_vdev_alloc_rollback:
+       video_device_release(jpeg->vfd_decoder);
+
+enc_vdev_register_rollback:
+       video_unregister_device(jpeg->vfd_encoder);
+
+enc_vdev_alloc_rollback:
+       video_device_release(jpeg->vfd_encoder);
+
+vb2_allocator_rollback:
+       vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
+
+m2m_init_rollback:
+       v4l2_m2m_release(jpeg->m2m_dev);
+
+device_register_rollback:
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+
+clk_get_rollback:
+       clk_disable(jpeg->clk);
+       clk_put(jpeg->clk);
+
+request_irq_rollback:
+       free_irq(jpeg->irq, jpeg);
+
+ioremap_rollback:
+       iounmap(jpeg->regs);
+
+mem_region_rollback:
+       release_resource(jpeg->ioarea);
+       release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea));
+
+jpeg_alloc_rollback:
+       kfree(jpeg);
+       return ret;
+}
+
+static int s5p_jpeg_remove(struct platform_device *pdev)
+{
+       struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
+
+       pm_runtime_disable(jpeg->dev);
+
+       video_unregister_device(jpeg->vfd_decoder);
+       video_device_release(jpeg->vfd_decoder);
+       video_unregister_device(jpeg->vfd_encoder);
+       video_device_release(jpeg->vfd_encoder);
+       vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
+       v4l2_m2m_release(jpeg->m2m_dev);
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+
+       clk_disable(jpeg->clk);
+       clk_put(jpeg->clk);
+
+       free_irq(jpeg->irq, jpeg);
+
+       iounmap(jpeg->regs);
+
+       release_resource(jpeg->ioarea);
+       release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea));
+       kfree(jpeg);
+
+       return 0;
+}
+
+static int s5p_jpeg_runtime_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int s5p_jpeg_runtime_resume(struct device *dev)
+{
+       struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+       /*
+        * JPEG IP allows storing two Huffman tables for each component
+        * We fill table 0 for each component
+        */
+       jpeg_set_hdctbl(jpeg->regs);
+       jpeg_set_hdctblg(jpeg->regs);
+       jpeg_set_hactbl(jpeg->regs);
+       jpeg_set_hactblg(jpeg->regs);
+       return 0;
+}
+
+static const struct dev_pm_ops s5p_jpeg_pm_ops = {
+       .runtime_suspend = s5p_jpeg_runtime_suspend,
+       .runtime_resume  = s5p_jpeg_runtime_resume,
+};
+
+static struct platform_driver s5p_jpeg_driver = {
+       .probe = s5p_jpeg_probe,
+       .remove = s5p_jpeg_remove,
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = S5P_JPEG_M2M_NAME,
+               .pm = &s5p_jpeg_pm_ops,
+       },
+};
+
+static int __init
+s5p_jpeg_register(void)
+{
+       int ret;
+
+       pr_info("S5P JPEG V4L2 Driver, (c) 2011 Samsung Electronics\n");
+
+       ret = platform_driver_register(&s5p_jpeg_driver);
+
+       if (ret)
+               pr_err("%s: failed to register jpeg driver\n", __func__);
+
+       return ret;
+}
+
+static void __exit
+s5p_jpeg_unregister(void)
+{
+       platform_driver_unregister(&s5p_jpeg_driver);
+}
+
+module_init(s5p_jpeg_register);
+module_exit(s5p_jpeg_unregister);
+
+MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
+MODULE_DESCRIPTION("Samsung JPEG codec driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.h b/drivers/media/video/s5p-jpeg/jpeg-core.h
new file mode 100644 (file)
index 0000000..facad61
--- /dev/null
@@ -0,0 +1,143 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 JPEG_CORE_H_
+#define JPEG_CORE_H_
+
+#include <media/v4l2-device.h>
+
+#define S5P_JPEG_M2M_NAME              "s5p-jpeg"
+
+/* JPEG compression quality setting */
+#define S5P_JPEG_COMPR_QUAL_BEST       0
+#define S5P_JPEG_COMPR_QUAL_WORST      3
+
+/* JPEG RGB to YCbCr conversion matrix coefficients */
+#define S5P_JPEG_COEF11                        0x4d
+#define S5P_JPEG_COEF12                        0x97
+#define S5P_JPEG_COEF13                        0x1e
+#define S5P_JPEG_COEF21                        0x2c
+#define S5P_JPEG_COEF22                        0x57
+#define S5P_JPEG_COEF23                        0x83
+#define S5P_JPEG_COEF31                        0x83
+#define S5P_JPEG_COEF32                        0x6e
+#define S5P_JPEG_COEF33                        0x13
+
+/* a selection of JPEG markers */
+#define TEM                            0x01
+#define SOF0                           0xc0
+#define RST                            0xd0
+#define SOI                            0xd8
+#define EOI                            0xd9
+#define DHP                            0xde
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE                        (1 << 0)
+#define MEM2MEM_OUTPUT                 (1 << 1)
+
+/**
+ * struct s5p_jpeg - JPEG IP abstraction
+ * @lock:              the mutex protecting this structure
+ * @v4l2_dev:          v4l2 device for mem2mem mode
+ * @vfd_encoder:       video device node for encoder mem2mem mode
+ * @vfd_decoder:       video device node for decoder mem2mem mode
+ * @m2m_dev:           v4l2 mem2mem device data
+ * @ioarea:            JPEG IP memory region
+ * @regs:              JPEG IP registers mapping
+ * @irq:               JPEG IP irq
+ * @clk:               JPEG IP clock
+ * @dev:               JPEG IP struct device
+ * @alloc_ctx:         videobuf2 memory allocator's context
+ */
+struct s5p_jpeg {
+       struct mutex            lock;
+
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd_encoder;
+       struct video_device     *vfd_decoder;
+       struct v4l2_m2m_dev     *m2m_dev;
+
+       struct resource         *ioarea;
+       void __iomem            *regs;
+       unsigned int            irq;
+       struct clk              *clk;
+       struct device           *dev;
+       void                    *alloc_ctx;
+};
+
+/**
+ * struct jpeg_fmt - driver's internal color format data
+ * @name:      format descritpion
+ * @fourcc:    the fourcc code, 0 if not applicable
+ * @depth:     number of bits per pixel
+ * @colplanes: number of color planes (1 for packed formats)
+ * @h_align:   horizontal alignment order (align to 2^h_align)
+ * @v_align:   vertical alignment order (align to 2^v_align)
+ * @types:     types of queue this format is applicable to
+ */
+struct s5p_jpeg_fmt {
+       char    *name;
+       u32     fourcc;
+       int     depth;
+       int     colplanes;
+       int     h_align;
+       int     v_align;
+       u32     types;
+};
+
+/**
+ * s5p_jpeg_q_data - parameters of one queue
+ * @fmt:       driver-specific format of this queue
+ * @w:         image width
+ * @h:         image height
+ * @size:      image buffer size in bytes
+ */
+struct s5p_jpeg_q_data {
+       struct s5p_jpeg_fmt     *fmt;
+       u32                     w;
+       u32                     h;
+       u32                     size;
+};
+
+/**
+ * s5p_jpeg_ctx - the device context data
+ * @jpeg:              JPEG IP device for this context
+ * @mode:              compression (encode) operation or decompression (decode)
+ * @compr_quality:     destination image quality in compression (encode) mode
+ * @m2m_ctx:           mem2mem device context
+ * @out_q:             source (output) queue information
+ * @cap_fmt:           destination (capture) queue queue information
+ * @hdr_parsed:                set if header has been parsed during decompression
+ */
+struct s5p_jpeg_ctx {
+       struct s5p_jpeg         *jpeg;
+       unsigned int            mode;
+       unsigned int            compr_quality;
+       struct v4l2_m2m_ctx     *m2m_ctx;
+       struct s5p_jpeg_q_data  out_q;
+       struct s5p_jpeg_q_data  cap_q;
+       bool                    hdr_parsed;
+};
+
+/**
+ * s5p_jpeg_buffer - description of memory containing input JPEG data
+ * @size:      buffer size
+ * @curr:      current position in the buffer
+ * @data:      pointer to the data
+ */
+struct s5p_jpeg_buffer {
+       unsigned long size;
+       unsigned long curr;
+       unsigned long data;
+};
+
+#endif /* JPEG_CORE_H */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw.h b/drivers/media/video/s5p-jpeg/jpeg-hw.h
new file mode 100644 (file)
index 0000000..e10c744
--- /dev/null
@@ -0,0 +1,353 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 JPEG_HW_H_
+#define JPEG_HW_H_
+
+#include <linux/io.h>
+
+#include "jpeg-hw.h"
+#include "jpeg-regs.h"
+
+#define S5P_JPEG_MIN_WIDTH             32
+#define S5P_JPEG_MIN_HEIGHT            32
+#define S5P_JPEG_MAX_WIDTH             8192
+#define S5P_JPEG_MAX_HEIGHT            8192
+#define S5P_JPEG_ENCODE                        0
+#define S5P_JPEG_DECODE                        1
+#define S5P_JPEG_RAW_IN_565            0
+#define S5P_JPEG_RAW_IN_422            1
+#define S5P_JPEG_SUBSAMPLING_422       0
+#define S5P_JPEG_SUBSAMPLING_420       1
+#define S5P_JPEG_RAW_OUT_422           0
+#define S5P_JPEG_RAW_OUT_420           1
+
+static inline void jpeg_reset(void __iomem *regs)
+{
+       unsigned long reg;
+
+       writel(1, regs + S5P_JPG_SW_RESET);
+       reg = readl(regs + S5P_JPG_SW_RESET);
+       /* no other way but polling for when JPEG IP becomes operational */
+       while (reg != 0) {
+               cpu_relax();
+               reg = readl(regs + S5P_JPG_SW_RESET);
+       }
+}
+
+static inline void jpeg_poweron(void __iomem *regs)
+{
+       writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
+}
+
+static inline void jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
+{
+       unsigned long reg, m;
+
+       m = S5P_MOD_SEL_565;
+       if (mode == S5P_JPEG_RAW_IN_565)
+               m = S5P_MOD_SEL_565;
+       else if (mode == S5P_JPEG_RAW_IN_422)
+               m = S5P_MOD_SEL_422;
+
+       reg = readl(regs + S5P_JPGCMOD);
+       reg &= ~S5P_MOD_SEL_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGCMOD);
+}
+
+static inline void jpeg_input_raw_y16(void __iomem *regs, bool y16)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGCMOD);
+       if (y16)
+               reg |= S5P_MODE_Y16;
+       else
+               reg &= ~S5P_MODE_Y16_MASK;
+       writel(reg, regs + S5P_JPGCMOD);
+}
+
+static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode)
+{
+       unsigned long reg, m;
+
+       m = S5P_PROC_MODE_DECOMPR;
+       if (mode == S5P_JPEG_ENCODE)
+               m = S5P_PROC_MODE_COMPR;
+       else
+               m = S5P_PROC_MODE_DECOMPR;
+       reg = readl(regs + S5P_JPGMOD);
+       reg &= ~S5P_PROC_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGMOD);
+}
+
+static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode)
+{
+       unsigned long reg, m;
+
+       m = S5P_SUBSAMPLING_MODE_422;
+       if (mode == S5P_JPEG_SUBSAMPLING_422)
+               m = S5P_SUBSAMPLING_MODE_422;
+       else if (mode == S5P_JPEG_SUBSAMPLING_420)
+               m = S5P_SUBSAMPLING_MODE_420;
+       reg = readl(regs + S5P_JPGMOD);
+       reg &= ~S5P_SUBSAMPLING_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGMOD);
+}
+
+static inline void jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGDRI_U);
+       reg &= ~0xff;
+       reg |= (dri >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGDRI_U);
+
+       reg = readl(regs + S5P_JPGDRI_L);
+       reg &= ~0xff;
+       reg |= dri & 0xff;
+       writel(reg, regs + S5P_JPGDRI_L);
+}
+
+static inline void jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_QTBL);
+       reg &= ~S5P_QT_NUMt_MASK(t);
+       reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
+       writel(reg, regs + S5P_JPG_QTBL);
+}
+
+static inline void jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_HTBL);
+       reg &= ~S5P_HT_NUMt_AC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
+       writel(reg, regs + S5P_JPG_HTBL);
+}
+
+static inline void jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_HTBL);
+       reg &= ~S5P_HT_NUMt_DC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
+       writel(reg, regs + S5P_JPG_HTBL);
+}
+
+static inline void jpeg_y(void __iomem *regs, unsigned int y)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGY_U);
+       reg &= ~0xff;
+       reg |= (y >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGY_U);
+
+       reg = readl(regs + S5P_JPGY_L);
+       reg &= ~0xff;
+       reg |= y & 0xff;
+       writel(reg, regs + S5P_JPGY_L);
+}
+
+static inline void jpeg_x(void __iomem *regs, unsigned int x)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGX_U);
+       reg &= ~0xff;
+       reg |= (x >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGX_U);
+
+       reg = readl(regs + S5P_JPGX_L);
+       reg &= ~0xff;
+       reg |= x & 0xff;
+       writel(reg, regs + S5P_JPGX_L);
+}
+
+static inline void jpeg_rst_int_enable(void __iomem *regs, bool enable)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_RSTm_INT_EN_MASK;
+       if (enable)
+               reg |= S5P_RSTm_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_data_num_int_enable(void __iomem *regs, bool enable)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_DATA_NUM_INT_EN_MASK;
+       if (enable)
+               reg |= S5P_DATA_NUM_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
+       if (enbl)
+               reg |= S5P_FINAL_MCU_NUM_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_timer_enable(void __iomem *regs, unsigned long val)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_TIMER_SE);
+       reg |= S5P_TIMER_INT_EN;
+       reg &= ~S5P_TIMER_INIT_MASK;
+       reg |= val & S5P_TIMER_INIT_MASK;
+       writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline void jpeg_timer_disable(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_TIMER_SE);
+       reg &= ~S5P_TIMER_INT_EN_MASK;
+       writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline int jpeg_timer_stat(void __iomem *regs)
+{
+       return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
+                    >> S5P_TIMER_INT_STAT_SHIFT);
+}
+
+static inline void jpeg_clear_timer_stat(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_TIMER_SE);
+       reg &= ~S5P_TIMER_INT_STAT_MASK;
+       writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline void jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+       reg &= ~S5P_ENC_STREAM_BOUND_MASK;
+       reg |= S5P_ENC_STREAM_INT_EN;
+       reg |= size & S5P_ENC_STREAM_BOUND_MASK;
+       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+static inline int jpeg_enc_stream_stat(void __iomem *regs)
+{
+       return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
+                    S5P_ENC_STREAM_INT_STAT_MASK);
+}
+
+static inline void jpeg_clear_enc_stream_stat(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+       reg &= ~S5P_ENC_STREAM_INT_MASK;
+       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+static inline void jpeg_outform_raw(void __iomem *regs, unsigned long format)
+{
+       unsigned long reg, f;
+
+       f = S5P_DEC_OUT_FORMAT_422;
+       if (format == S5P_JPEG_RAW_OUT_422)
+               f = S5P_DEC_OUT_FORMAT_422;
+       else if (format == S5P_JPEG_RAW_OUT_420)
+               f = S5P_DEC_OUT_FORMAT_420;
+       reg = readl(regs + S5P_JPG_OUTFORM);
+       reg &= ~S5P_DEC_OUT_FORMAT_MASK;
+       reg |= f;
+       writel(reg, regs + S5P_JPG_OUTFORM);
+}
+
+static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr)
+{
+       writel(addr, regs + S5P_JPG_JPGADR);
+}
+
+static inline void jpeg_imgadr(void __iomem *regs, unsigned long addr)
+{
+       writel(addr, regs + S5P_JPG_IMGADR);
+}
+
+static inline void jpeg_coef(void __iomem *regs, unsigned int i,
+                            unsigned int j, unsigned int coef)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_COEF(i));
+       reg &= ~S5P_COEFn_MASK(j);
+       reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
+       writel(reg, regs + S5P_JPG_COEF(i));
+}
+
+static inline void jpeg_start(void __iomem *regs)
+{
+       writel(1, regs + S5P_JSTART);
+}
+
+static inline int jpeg_result_stat_ok(void __iomem *regs)
+{
+       return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
+                    >> S5P_RESULT_STAT_SHIFT);
+}
+
+static inline int jpeg_stream_stat_ok(void __iomem *regs)
+{
+       return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
+                     >> S5P_STREAM_STAT_SHIFT);
+}
+
+static inline void jpeg_clear_int(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTST);
+       writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
+       reg = readl(regs + S5P_JPGOPR);
+}
+
+static inline unsigned int jpeg_compressed_size(void __iomem *regs)
+{
+       unsigned long jpeg_size = 0;
+
+       jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
+       jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
+       jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
+
+       return (unsigned int)jpeg_size;
+}
+
+#endif /* JPEG_HW_H_ */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs.h b/drivers/media/video/s5p-jpeg/jpeg-regs.h
new file mode 100644 (file)
index 0000000..91f4dd5
--- /dev/null
@@ -0,0 +1,170 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-regs.h
+ *
+ * Register definition file for Samsung JPEG codec driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 JPEG_REGS_H_
+#define JPEG_REGS_H_
+
+/* JPEG mode register */
+#define S5P_JPGMOD                     0x00
+#define S5P_PROC_MODE_MASK             (0x1 << 3)
+#define S5P_PROC_MODE_DECOMPR          (0x1 << 3)
+#define S5P_PROC_MODE_COMPR            (0x0 << 3)
+#define S5P_SUBSAMPLING_MODE_MASK      0x7
+#define S5P_SUBSAMPLING_MODE_444       (0x0 << 0)
+#define S5P_SUBSAMPLING_MODE_422       (0x1 << 0)
+#define S5P_SUBSAMPLING_MODE_420       (0x2 << 0)
+#define S5P_SUBSAMPLING_MODE_GRAY      (0x3 << 0)
+
+/* JPEG operation status register */
+#define S5P_JPGOPR                     0x04
+
+/* Quantization tables*/
+#define S5P_JPG_QTBL                   0x08
+#define S5P_QT_NUMt_SHIFT(t)           (((t) - 1) << 1)
+#define S5P_QT_NUMt_MASK(t)            (0x3 << S5P_QT_NUMt_SHIFT(t))
+
+/* Huffman tables */
+#define S5P_JPG_HTBL                   0x0c
+#define S5P_HT_NUMt_AC_SHIFT(t)                (((t) << 1) - 1)
+#define S5P_HT_NUMt_AC_MASK(t)         (0x1 << S5P_HT_NUMt_AC_SHIFT(t))
+
+#define S5P_HT_NUMt_DC_SHIFT(t)                (((t) - 1) << 1)
+#define S5P_HT_NUMt_DC_MASK(t)         (0x1 << S5P_HT_NUMt_DC_SHIFT(t))
+
+/* JPEG restart interval register upper byte */
+#define S5P_JPGDRI_U                   0x10
+
+/* JPEG restart interval register lower byte */
+#define S5P_JPGDRI_L                   0x14
+
+/* JPEG vertical resolution register upper byte */
+#define S5P_JPGY_U                     0x18
+
+/* JPEG vertical resolution register lower byte */
+#define S5P_JPGY_L                     0x1c
+
+/* JPEG horizontal resolution register upper byte */
+#define S5P_JPGX_U                     0x20
+
+/* JPEG horizontal resolution register lower byte */
+#define S5P_JPGX_L                     0x24
+
+/* JPEG byte count register upper byte */
+#define S5P_JPGCNT_U                   0x28
+
+/* JPEG byte count register middle byte */
+#define S5P_JPGCNT_M                   0x2c
+
+/* JPEG byte count register lower byte */
+#define S5P_JPGCNT_L                   0x30
+
+/* JPEG interrupt setting register */
+#define S5P_JPGINTSE                   0x34
+#define S5P_RSTm_INT_EN_MASK           (0x1 << 7)
+#define S5P_RSTm_INT_EN                        (0x1 << 7)
+#define S5P_DATA_NUM_INT_EN_MASK       (0x1 << 6)
+#define S5P_DATA_NUM_INT_EN            (0x1 << 6)
+#define S5P_FINAL_MCU_NUM_INT_EN_MASK  (0x1 << 5)
+#define S5P_FINAL_MCU_NUM_INT_EN       (0x1 << 5)
+
+/* JPEG interrupt status register */
+#define S5P_JPGINTST                   0x38
+#define S5P_RESULT_STAT_SHIFT          6
+#define S5P_RESULT_STAT_MASK           (0x1 << S5P_RESULT_STAT_SHIFT)
+#define S5P_STREAM_STAT_SHIFT          5
+#define S5P_STREAM_STAT_MASK           (0x1 << S5P_STREAM_STAT_SHIFT)
+
+/* JPEG command register */
+#define S5P_JPGCOM                     0x4c
+#define S5P_INT_RELEASE                        (0x1 << 2)
+
+/* Raw image data r/w address register */
+#define S5P_JPG_IMGADR                 0x50
+
+/* JPEG file r/w address register */
+#define S5P_JPG_JPGADR                 0x58
+
+/* Coefficient for RGB-to-YCbCr converter register */
+#define S5P_JPG_COEF(n)                        (0x5c + (((n) - 1) << 2))
+#define S5P_COEFn_SHIFT(j)             ((3 - (j)) << 3)
+#define S5P_COEFn_MASK(j)              (0xff << S5P_COEFn_SHIFT(j))
+
+/* JPEG color mode register */
+#define S5P_JPGCMOD                    0x68
+#define S5P_MOD_SEL_MASK               (0x7 << 5)
+#define S5P_MOD_SEL_422                        (0x1 << 5)
+#define S5P_MOD_SEL_565                        (0x2 << 5)
+#define S5P_MODE_Y16_MASK              (0x1 << 1)
+#define S5P_MODE_Y16                   (0x1 << 1)
+
+/* JPEG clock control register */
+#define S5P_JPGCLKCON                  0x6c
+#define S5P_CLK_DOWN_READY             (0x1 << 1)
+#define S5P_POWER_ON                   (0x1 << 0)
+
+/* JPEG start register */
+#define S5P_JSTART                     0x70
+
+/* JPEG SW reset register */
+#define S5P_JPG_SW_RESET               0x78
+
+/* JPEG timer setting register */
+#define S5P_JPG_TIMER_SE               0x7c
+#define S5P_TIMER_INT_EN_MASK          (0x1 << 31)
+#define S5P_TIMER_INT_EN               (0x1 << 31)
+#define S5P_TIMER_INIT_MASK            0x7fffffff
+
+/* JPEG timer status register */
+#define S5P_JPG_TIMER_ST               0x80
+#define S5P_TIMER_INT_STAT_SHIFT       31
+#define S5P_TIMER_INT_STAT_MASK                (0x1 << S5P_TIMER_INT_STAT_SHIFT)
+#define S5P_TIMER_CNT_SHIFT            0
+#define S5P_TIMER_CNT_MASK             0x7fffffff
+
+/* JPEG decompression output format register */
+#define S5P_JPG_OUTFORM                        0x88
+#define S5P_DEC_OUT_FORMAT_MASK                (0x1 << 0)
+#define S5P_DEC_OUT_FORMAT_422         (0x0 << 0)
+#define S5P_DEC_OUT_FORMAT_420         (0x1 << 0)
+
+/* JPEG version register */
+#define S5P_JPG_VERSION                        0x8c
+
+/* JPEG compressed stream size interrupt setting register */
+#define S5P_JPG_ENC_STREAM_INTSE       0x98
+#define S5P_ENC_STREAM_INT_MASK                (0x1 << 24)
+#define S5P_ENC_STREAM_INT_EN          (0x1 << 24)
+#define S5P_ENC_STREAM_BOUND_MASK      0xffffff
+
+/* JPEG compressed stream size interrupt status register */
+#define S5P_JPG_ENC_STREAM_INTST       0x9c
+#define S5P_ENC_STREAM_INT_STAT_MASK   0x1
+
+/* JPEG quantizer table register */
+#define S5P_JPG_QTBL_CONTENT(n)                (0x400 + (n) * 0x100)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBL(n)              (0x800 + (n) * 0x400)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBLG(n)             (0x840 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBL(n)              (0x880 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBLG(n)             (0x8c0 + (n) * 0x400)
+
+#endif /* JPEG_REGS_H_ */
+
index 8be8b54eb749769449a49f68fcf23f57b3628bd9..e43e128baf5f7c3ec7051337a1574821e9e863a2 100644 (file)
@@ -1245,27 +1245,7 @@ static struct platform_driver s5p_mfc_driver = {
        },
 };
 
-static char banner[] __initdata =
-                       "S5P MFC V4L2 Driver, (C) 2011 Samsung Electronics\n";
-
-static int __init s5p_mfc_init(void)
-{
-       int ret;
-
-       pr_info("%s", banner);
-       ret = platform_driver_register(&s5p_mfc_driver);
-       if (ret)
-               pr_err("Platform device registration failed.\n");
-       return ret;
-}
-
-static void __exit s5p_mfc_exit(void)
-{
-       platform_driver_unregister(&s5p_mfc_driver);
-}
-
-module_init(s5p_mfc_init);
-module_exit(s5p_mfc_exit);
+module_platform_driver(s5p_mfc_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
index 0279e6e89febaf74db82d92c5ea783ab557ce187..8b41a0410ab175ab3968ad66036c6290301a6a68 100644 (file)
@@ -838,8 +838,8 @@ static int hdmi_resources_init(struct hdmi_device *hdev)
                dev_err(dev, "failed to get clock 'hdmiphy'\n");
                goto fail;
        }
-       res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
-               sizeof res->regul_bulk[0], GFP_KERNEL);
+       res->regul_bulk = kcalloc(ARRAY_SIZE(supply),
+                                 sizeof(res->regul_bulk[0]), GFP_KERNEL);
        if (!res->regul_bulk) {
                dev_err(dev, "failed to get memory for regulators\n");
                goto fail;
@@ -1016,28 +1016,4 @@ static struct platform_driver hdmi_driver __refdata = {
        }
 };
 
-/* D R I V E R   I N I T I A L I Z A T I O N */
-
-static int __init hdmi_init(void)
-{
-       int ret;
-       static const char banner[] __initdata = KERN_INFO \
-               "Samsung HDMI output driver, "
-               "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
-       printk(banner);
-
-       ret = platform_driver_register(&hdmi_driver);
-       if (ret)
-               printk(KERN_ERR "HDMI platform driver register failed\n");
-
-       return ret;
-}
-module_init(hdmi_init);
-
-static void __exit hdmi_exit(void)
-{
-       platform_driver_unregister(&hdmi_driver);
-}
-module_exit(hdmi_exit);
-
-
+module_platform_driver(hdmi_driver);
index 51ad59b30358aa7e869a94d6d68df581e2d7b539..1597078c4a5070043270d1b54b9d980ba6cadc90 100644 (file)
@@ -86,6 +86,17 @@ struct mxr_crop {
        unsigned int field;
 };
 
+/** stages of geometry operations */
+enum mxr_geometry_stage {
+       MXR_GEOMETRY_SINK,
+       MXR_GEOMETRY_COMPOSE,
+       MXR_GEOMETRY_CROP,
+       MXR_GEOMETRY_SOURCE,
+};
+
+/* flag indicating that offset should be 0 */
+#define MXR_NO_OFFSET  0x80000000
+
 /** description of transformation from source to destination image */
 struct mxr_geometry {
        /** cropping for source image */
@@ -133,7 +144,8 @@ struct mxr_layer_ops {
        /** streaming stop/start */
        void (*stream_set)(struct mxr_layer *, int);
        /** adjusting geometry */
-       void (*fix_geometry)(struct mxr_layer *);
+       void (*fix_geometry)(struct mxr_layer *,
+               enum mxr_geometry_stage, unsigned long);
 };
 
 /** layer instance, a single window and content displayed on output */
index de8270c2b6e7d408569d1c731f9549579153b548..b93a21f5aa131656cbc62649e164031ca3a08c86 100644 (file)
@@ -101,47 +101,132 @@ static void mxr_graph_format_set(struct mxr_layer *layer)
                layer->fmt, &layer->geo);
 }
 
-static void mxr_graph_fix_geometry(struct mxr_layer *layer)
+static inline unsigned int closest(unsigned int x, unsigned int a,
+       unsigned int b, unsigned long flags)
+{
+       unsigned int mid = (a + b) / 2;
+
+       /* choosing closest value with constraints according to table:
+        * -------------+-----+-----+-----+-------+
+        * flags        |  0  |  LE |  GE | LE|GE |
+        * -------------+-----+-----+-----+-------+
+        * x <= a       |  a  |  a  |  a  |   a   |
+        * a < x <= mid |  a  |  a  |  b  |   a   |
+        * mid < x < b  |  b  |  a  |  b  |   b   |
+        * b <= x       |  b  |  b  |  b  |   b   |
+        * -------------+-----+-----+-----+-------+
+        */
+
+       /* remove all non-constraint flags */
+       flags &= V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE;
+
+       if (x <= a)
+               return  a;
+       if (x >= b)
+               return b;
+       if (flags == V4L2_SEL_FLAG_LE)
+               return a;
+       if (flags == V4L2_SEL_FLAG_GE)
+               return b;
+       if (x <= mid)
+               return a;
+       return b;
+}
+
+static inline unsigned int do_center(unsigned int center,
+       unsigned int size, unsigned int upper, unsigned int flags)
+{
+       unsigned int lower;
+
+       if (flags & MXR_NO_OFFSET)
+               return 0;
+
+       lower = center - min(center, size / 2);
+       return min(lower, upper - size);
+}
+
+static void mxr_graph_fix_geometry(struct mxr_layer *layer,
+       enum mxr_geometry_stage stage, unsigned long flags)
 {
        struct mxr_geometry *geo = &layer->geo;
+       struct mxr_crop *src = &geo->src;
+       struct mxr_crop *dst = &geo->dst;
+       unsigned int x_center, y_center;
 
-       /* limit to boundary size */
-       geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
-       geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
-       geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width);
-       geo->src.width = min(geo->src.width, 2047U);
-       /* not possible to crop of Y axis */
-       geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1);
-       geo->src.height = geo->src.full_height - geo->src.y_offset;
-       /* limitting offset */
-       geo->src.x_offset = min(geo->src.x_offset,
-               geo->src.full_width - geo->src.width);
-
-       /* setting position in output */
-       geo->dst.width = min(geo->dst.width, geo->dst.full_width);
-       geo->dst.height = min(geo->dst.height, geo->dst.full_height);
-
-       /* Mixer supports only 1x and 2x scaling */
-       if (geo->dst.width >= 2 * geo->src.width) {
-               geo->x_ratio = 1;
-               geo->dst.width = 2 * geo->src.width;
-       } else {
-               geo->x_ratio = 0;
-               geo->dst.width = geo->src.width;
-       }
+       switch (stage) {
 
-       if (geo->dst.height >= 2 * geo->src.height) {
-               geo->y_ratio = 1;
-               geo->dst.height = 2 * geo->src.height;
-       } else {
-               geo->y_ratio = 0;
-               geo->dst.height = geo->src.height;
-       }
+       case MXR_GEOMETRY_SINK: /* nothing to be fixed here */
+               flags = 0;
+               /* fall through */
+
+       case MXR_GEOMETRY_COMPOSE:
+               /* remember center of the area */
+               x_center = dst->x_offset + dst->width / 2;
+               y_center = dst->y_offset + dst->height / 2;
+               /* round up/down to 2 multiple depending on flags */
+               if (flags & V4L2_SEL_FLAG_LE) {
+                       dst->width = round_down(dst->width, 2);
+                       dst->height = round_down(dst->height, 2);
+               } else {
+                       dst->width = round_up(dst->width, 2);
+                       dst->height = round_up(dst->height, 2);
+               }
+               /* assure that compose rect is inside display area */
+               dst->width = min(dst->width, dst->full_width);
+               dst->height = min(dst->height, dst->full_height);
+
+               /* ensure that compose is reachable using 2x scaling */
+               dst->width = min(dst->width, 2 * src->full_width);
+               dst->height = min(dst->height, 2 * src->full_height);
+
+               /* setup offsets */
+               dst->x_offset = do_center(x_center, dst->width,
+                       dst->full_width, flags);
+               dst->y_offset = do_center(y_center, dst->height,
+                       dst->full_height, flags);
+               flags = 0;
+               /* fall through */
 
-       geo->dst.x_offset = min(geo->dst.x_offset,
-               geo->dst.full_width - geo->dst.width);
-       geo->dst.y_offset = min(geo->dst.y_offset,
-               geo->dst.full_height - geo->dst.height);
+       case MXR_GEOMETRY_CROP:
+               /* remember center of the area */
+               x_center = src->x_offset + src->width / 2;
+               y_center = src->y_offset + src->height / 2;
+               /* ensure that cropping area lies inside the buffer */
+               if (src->full_width < dst->width)
+                       src->width = dst->width / 2;
+               else
+                       src->width = closest(src->width, dst->width / 2,
+                               dst->width, flags);
+
+               if (src->width == dst->width)
+                       geo->x_ratio = 0;
+               else
+                       geo->x_ratio = 1;
+
+               if (src->full_height < dst->height)
+                       src->height = dst->height / 2;
+               else
+                       src->height = closest(src->height, dst->height / 2,
+                               dst->height, flags);
+
+               if (src->height == dst->height)
+                       geo->y_ratio = 0;
+               else
+                       geo->y_ratio = 1;
+
+               /* setup offsets */
+               src->x_offset = do_center(x_center, src->width,
+                       src->full_width, flags);
+               src->y_offset = do_center(y_center, src->height,
+                       src->full_height, flags);
+               flags = 0;
+               /* fall through */
+       case MXR_GEOMETRY_SOURCE:
+               src->full_width = clamp_val(src->full_width,
+                       src->width + src->x_offset, 32767);
+               src->full_height = clamp_val(src->full_height,
+                       src->height + src->y_offset, 2047);
+       };
 }
 
 /* PUBLIC API */
index b47d0c06ecf5ab3ee66c911f1d035df1948b31e7..7884baeff76a8748133abda13659aedc48a6dff2 100644 (file)
@@ -170,18 +170,22 @@ static int mxr_querycap(struct file *file, void *priv,
        return 0;
 }
 
-/* Geometry handling */
-static void mxr_layer_geo_fix(struct mxr_layer *layer)
+static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo)
 {
-       struct mxr_device *mdev = layer->mdev;
-       struct v4l2_mbus_framefmt mbus_fmt;
-
-       /* TODO: add some dirty flag to avoid unnecessary adjustments */
-       mxr_get_mbus_fmt(mdev, &mbus_fmt);
-       layer->geo.dst.full_width = mbus_fmt.width;
-       layer->geo.dst.full_height = mbus_fmt.height;
-       layer->geo.dst.field = mbus_fmt.field;
-       layer->ops.fix_geometry(layer);
+       mxr_dbg(mdev, "src.full_size = (%u, %u)\n",
+               geo->src.full_width, geo->src.full_height);
+       mxr_dbg(mdev, "src.size = (%u, %u)\n",
+               geo->src.width, geo->src.height);
+       mxr_dbg(mdev, "src.offset = (%u, %u)\n",
+               geo->src.x_offset, geo->src.y_offset);
+       mxr_dbg(mdev, "dst.full_size = (%u, %u)\n",
+               geo->dst.full_width, geo->dst.full_height);
+       mxr_dbg(mdev, "dst.size = (%u, %u)\n",
+               geo->dst.width, geo->dst.height);
+       mxr_dbg(mdev, "dst.offset = (%u, %u)\n",
+               geo->dst.x_offset, geo->dst.y_offset);
+       mxr_dbg(mdev, "ratio = (%u, %u)\n",
+               geo->x_ratio, geo->y_ratio);
 }
 
 static void mxr_layer_default_geo(struct mxr_layer *layer)
@@ -204,27 +208,29 @@ static void mxr_layer_default_geo(struct mxr_layer *layer)
        layer->geo.src.width = layer->geo.src.full_width;
        layer->geo.src.height = layer->geo.src.full_height;
 
-       layer->ops.fix_geometry(layer);
+       mxr_geometry_dump(mdev, &layer->geo);
+       layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
+       mxr_geometry_dump(mdev, &layer->geo);
 }
 
-static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo)
+static void mxr_layer_update_output(struct mxr_layer *layer)
 {
-       mxr_dbg(mdev, "src.full_size = (%u, %u)\n",
-               geo->src.full_width, geo->src.full_height);
-       mxr_dbg(mdev, "src.size = (%u, %u)\n",
-               geo->src.width, geo->src.height);
-       mxr_dbg(mdev, "src.offset = (%u, %u)\n",
-               geo->src.x_offset, geo->src.y_offset);
-       mxr_dbg(mdev, "dst.full_size = (%u, %u)\n",
-               geo->dst.full_width, geo->dst.full_height);
-       mxr_dbg(mdev, "dst.size = (%u, %u)\n",
-               geo->dst.width, geo->dst.height);
-       mxr_dbg(mdev, "dst.offset = (%u, %u)\n",
-               geo->dst.x_offset, geo->dst.y_offset);
-       mxr_dbg(mdev, "ratio = (%u, %u)\n",
-               geo->x_ratio, geo->y_ratio);
-}
+       struct mxr_device *mdev = layer->mdev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       mxr_get_mbus_fmt(mdev, &mbus_fmt);
+       /* checking if update is needed */
+       if (layer->geo.dst.full_width == mbus_fmt.width &&
+               layer->geo.dst.full_height == mbus_fmt.width)
+               return;
 
+       layer->geo.dst.full_width = mbus_fmt.width;
+       layer->geo.dst.full_height = mbus_fmt.height;
+       layer->geo.dst.field = mbus_fmt.field;
+       layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
+
+       mxr_geometry_dump(mdev, &layer->geo);
+}
 
 static const struct mxr_format *find_format_by_fourcc(
        struct mxr_layer *layer, unsigned long fourcc);
@@ -249,37 +255,6 @@ static int mxr_enum_fmt(struct file *file, void  *priv,
        return 0;
 }
 
-static int mxr_s_fmt(struct file *file, void *priv,
-       struct v4l2_format *f)
-{
-       struct mxr_layer *layer = video_drvdata(file);
-       const struct mxr_format *fmt;
-       struct v4l2_pix_format_mplane *pix;
-       struct mxr_device *mdev = layer->mdev;
-       struct mxr_geometry *geo = &layer->geo;
-
-       mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
-
-       pix = &f->fmt.pix_mp;
-       fmt = find_format_by_fourcc(layer, pix->pixelformat);
-       if (fmt == NULL) {
-               mxr_warn(mdev, "not recognized fourcc: %08x\n",
-                       pix->pixelformat);
-               return -EINVAL;
-       }
-       layer->fmt = fmt;
-       geo->src.full_width = pix->width;
-       geo->src.width = pix->width;
-       geo->src.full_height = pix->height;
-       geo->src.height = pix->height;
-       /* assure consistency of geometry */
-       mxr_layer_geo_fix(layer);
-       mxr_dbg(mdev, "width=%u height=%u span=%u\n",
-               geo->src.width, geo->src.height, geo->src.full_width);
-
-       return 0;
-}
-
 static unsigned int divup(unsigned int divident, unsigned int divisor)
 {
        return (divident + divisor - 1) / divisor;
@@ -299,6 +274,10 @@ static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes,
 {
        int i;
 
+       /* checking if nothing to fill */
+       if (!planes)
+               return;
+
        memset(planes, 0, sizeof(*planes) * fmt->num_subframes);
        for (i = 0; i < fmt->num_planes; ++i) {
                struct v4l2_plane_pix_format *plane = planes
@@ -332,73 +311,194 @@ static int mxr_g_fmt(struct file *file, void *priv,
        return 0;
 }
 
-static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo,
-       enum v4l2_buf_type type)
-{
-       switch (type) {
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               return &geo->dst;
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               return &geo->src;
-       default:
-               return NULL;
-       }
-}
-
-static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+static int mxr_s_fmt(struct file *file, void *priv,
+       struct v4l2_format *f)
 {
        struct mxr_layer *layer = video_drvdata(file);
-       struct mxr_crop *crop;
+       const struct mxr_format *fmt;
+       struct v4l2_pix_format_mplane *pix;
+       struct mxr_device *mdev = layer->mdev;
+       struct mxr_geometry *geo = &layer->geo;
 
-       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
-       crop = choose_crop_by_type(&layer->geo, a->type);
-       if (crop == NULL)
+       mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
+
+       pix = &f->fmt.pix_mp;
+       fmt = find_format_by_fourcc(layer, pix->pixelformat);
+       if (fmt == NULL) {
+               mxr_warn(mdev, "not recognized fourcc: %08x\n",
+                       pix->pixelformat);
                return -EINVAL;
-       mxr_layer_geo_fix(layer);
-       a->c.left = crop->x_offset;
-       a->c.top = crop->y_offset;
-       a->c.width = crop->width;
-       a->c.height = crop->height;
+       }
+       layer->fmt = fmt;
+       /* set source size to highest accepted value */
+       geo->src.full_width = max(geo->dst.full_width, pix->width);
+       geo->src.full_height = max(geo->dst.full_height, pix->height);
+       layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
+       mxr_geometry_dump(mdev, &layer->geo);
+       /* set cropping to total visible screen */
+       geo->src.width = pix->width;
+       geo->src.height = pix->height;
+       geo->src.x_offset = 0;
+       geo->src.y_offset = 0;
+       /* assure consistency of geometry */
+       layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET);
+       mxr_geometry_dump(mdev, &layer->geo);
+       /* set full size to lowest possible value */
+       geo->src.full_width = 0;
+       geo->src.full_height = 0;
+       layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
+       mxr_geometry_dump(mdev, &layer->geo);
+
+       /* returning results */
+       mxr_g_fmt(file, priv, f);
+
        return 0;
 }
 
-static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+static int mxr_g_selection(struct file *file, void *fh,
+       struct v4l2_selection *s)
 {
        struct mxr_layer *layer = video_drvdata(file);
-       struct mxr_crop *crop;
+       struct mxr_geometry *geo = &layer->geo;
 
        mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
-       crop = choose_crop_by_type(&layer->geo, a->type);
-       if (crop == NULL)
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+               s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return -EINVAL;
+
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP_ACTIVE:
+               s->r.left = geo->src.x_offset;
+               s->r.top = geo->src.y_offset;
+               s->r.width = geo->src.width;
+               s->r.height = geo->src.height;
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = geo->src.full_width;
+               s->r.height = geo->src.full_height;
+               break;
+       case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+       case V4L2_SEL_TGT_COMPOSE_PADDED:
+               s->r.left = geo->dst.x_offset;
+               s->r.top = geo->dst.y_offset;
+               s->r.width = geo->dst.width;
+               s->r.height = geo->dst.height;
+               break;
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = geo->dst.full_width;
+               s->r.height = geo->dst.full_height;
+               break;
+       default:
                return -EINVAL;
-       crop->x_offset = a->c.left;
-       crop->y_offset = a->c.top;
-       crop->width = a->c.width;
-       crop->height = a->c.height;
-       mxr_layer_geo_fix(layer);
+       }
+
        return 0;
 }
 
-static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
+/* returns 1 if rectangle 'a' is inside 'b' */
+static int mxr_is_rect_inside(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+       if (a->left < b->left)
+               return 0;
+       if (a->top < b->top)
+               return 0;
+       if (a->left + a->width > b->left + b->width)
+               return 0;
+       if (a->top + a->height > b->top + b->height)
+               return 0;
+       return 1;
+}
+
+static int mxr_s_selection(struct file *file, void *fh,
+       struct v4l2_selection *s)
 {
        struct mxr_layer *layer = video_drvdata(file);
-       struct mxr_crop *crop;
+       struct mxr_geometry *geo = &layer->geo;
+       struct mxr_crop *target = NULL;
+       enum mxr_geometry_stage stage;
+       struct mxr_geometry tmp;
+       struct v4l2_rect res;
 
-       mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
-       crop = choose_crop_by_type(&layer->geo, a->type);
-       if (crop == NULL)
+       memset(&res, 0, sizeof res);
+
+       mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__,
+               s->r.width, s->r.height, s->r.left, s->r.top);
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+               s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
                return -EINVAL;
-       mxr_layer_geo_fix(layer);
-       a->bounds.left = 0;
-       a->bounds.top = 0;
-       a->bounds.width = crop->full_width;
-       a->bounds.top = crop->full_height;
-       a->defrect = a->bounds;
-       /* setting pixel aspect to 1/1 */
-       a->pixelaspect.numerator = 1;
-       a->pixelaspect.denominator = 1;
+
+       switch (s->target) {
+       /* ignore read-only targets */
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               res.width = geo->src.full_width;
+               res.height = geo->src.full_height;
+               break;
+
+       /* ignore read-only targets */
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               res.width = geo->dst.full_width;
+               res.height = geo->dst.full_height;
+               break;
+
+       case V4L2_SEL_TGT_CROP_ACTIVE:
+               target = &geo->src;
+               stage = MXR_GEOMETRY_CROP;
+               break;
+       case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+       case V4L2_SEL_TGT_COMPOSE_PADDED:
+               target = &geo->dst;
+               stage = MXR_GEOMETRY_COMPOSE;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* apply change and update geometry if needed */
+       if (target) {
+               /* backup current geometry if setup fails */
+               memcpy(&tmp, geo, sizeof tmp);
+
+               /* apply requested selection */
+               target->x_offset = s->r.left;
+               target->y_offset = s->r.top;
+               target->width = s->r.width;
+               target->height = s->r.height;
+
+               layer->ops.fix_geometry(layer, stage, s->flags);
+
+               /* retrieve update selection rectangle */
+               res.left = target->x_offset;
+               res.top = target->y_offset;
+               res.width = target->width;
+               res.height = target->height;
+
+               mxr_geometry_dump(layer->mdev, &layer->geo);
+       }
+
+       /* checking if the rectangle satisfies constraints */
+       if ((s->flags & V4L2_SEL_FLAG_LE) && !mxr_is_rect_inside(&res, &s->r))
+               goto fail;
+       if ((s->flags & V4L2_SEL_FLAG_GE) && !mxr_is_rect_inside(&s->r, &res))
+               goto fail;
+
+       /* return result rectangle */
+       s->r = res;
+
        return 0;
+fail:
+       /* restore old geometry, which is not touched if target is NULL */
+       if (target)
+               memcpy(geo, &tmp, sizeof tmp);
+       return -ERANGE;
 }
 
 static int mxr_enum_dv_presets(struct file *file, void *fh,
@@ -438,6 +538,8 @@ static int mxr_s_dv_preset(struct file *file, void *fh,
 
        mutex_unlock(&mdev->mutex);
 
+       mxr_layer_update_output(layer);
+
        /* any failure should return EINVAL according to V4L2 doc */
        return ret ? -EINVAL : 0;
 }
@@ -478,6 +580,8 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
 
        mutex_unlock(&mdev->mutex);
 
+       mxr_layer_update_output(layer);
+
        return ret ? -EINVAL : 0;
 }
 
@@ -526,25 +630,27 @@ static int mxr_s_output(struct file *file, void *fh, unsigned int i)
        struct video_device *vfd = video_devdata(file);
        struct mxr_layer *layer = video_drvdata(file);
        struct mxr_device *mdev = layer->mdev;
-       int ret = 0;
 
        if (i >= mdev->output_cnt || mdev->output[i] == NULL)
                return -EINVAL;
 
        mutex_lock(&mdev->mutex);
        if (mdev->n_output > 0) {
-               ret = -EBUSY;
-               goto done;
+               mutex_unlock(&mdev->mutex);
+               return -EBUSY;
        }
        mdev->current_output = i;
        vfd->tvnorms = 0;
        v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output,
                &vfd->tvnorms);
+       mutex_unlock(&mdev->mutex);
+
+       /* update layers geometry */
+       mxr_layer_update_output(layer);
+
        mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms);
 
-done:
-       mutex_unlock(&mdev->mutex);
-       return ret;
+       return 0;
 }
 
 static int mxr_g_output(struct file *file, void *fh, unsigned int *p)
@@ -633,10 +739,9 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
        .vidioc_enum_output = mxr_enum_output,
        .vidioc_s_output = mxr_s_output,
        .vidioc_g_output = mxr_g_output,
-       /* Crop ioctls */
-       .vidioc_g_crop = mxr_g_crop,
-       .vidioc_s_crop = mxr_s_crop,
-       .vidioc_cropcap = mxr_cropcap,
+       /* selection ioctls */
+       .vidioc_g_selection = mxr_g_selection,
+       .vidioc_s_selection = mxr_s_selection,
 };
 
 static int mxr_video_open(struct file *file)
@@ -805,10 +910,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
        /* block any changes in output configuration */
        mxr_output_get(mdev);
 
-       /* update layers geometry */
-       mxr_layer_geo_fix(layer);
-       mxr_geometry_dump(mdev, &layer->geo);
-
+       mxr_layer_update_output(layer);
        layer->ops.format_set(layer);
        /* enabling layer in hardware */
        spin_lock_irqsave(&layer->enq_slock, flags);
index f3bb2e34cb517d11bdb1dd11d716cb18255f0e4b..3d13a636877be73ce50079a3d286014b6182b3c3 100644 (file)
@@ -127,47 +127,77 @@ static void mxr_vp_format_set(struct mxr_layer *layer)
        mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo);
 }
 
-static void mxr_vp_fix_geometry(struct mxr_layer *layer)
+static inline unsigned int do_center(unsigned int center,
+       unsigned int size, unsigned int upper, unsigned int flags)
 {
-       struct mxr_geometry *geo = &layer->geo;
+       unsigned int lower;
+
+       if (flags & MXR_NO_OFFSET)
+               return 0;
+
+       lower = center - min(center, size / 2);
+       return min(lower, upper - size);
+}
 
-       /* align horizontal size to 8 pixels */
-       geo->src.full_width = ALIGN(geo->src.full_width, 8);
-       /* limit to boundary size */
-       geo->src.full_width = clamp_val(geo->src.full_width, 8, 8192);
-       geo->src.full_height = clamp_val(geo->src.full_height, 1, 8192);
-       geo->src.width = clamp_val(geo->src.width, 32, geo->src.full_width);
-       geo->src.width = min(geo->src.width, 2047U);
-       geo->src.height = clamp_val(geo->src.height, 4, geo->src.full_height);
-       geo->src.height = min(geo->src.height, 2047U);
-
-       /* setting size of output window */
-       geo->dst.width = clamp_val(geo->dst.width, 8, geo->dst.full_width);
-       geo->dst.height = clamp_val(geo->dst.height, 1, geo->dst.full_height);
-
-       /* ensure that scaling is in range 1/4x to 16x */
-       if (geo->src.width >= 4 * geo->dst.width)
-               geo->src.width = 4 * geo->dst.width;
-       if (geo->dst.width >= 16 * geo->src.width)
-               geo->dst.width = 16 * geo->src.width;
-       if (geo->src.height >= 4 * geo->dst.height)
-               geo->src.height = 4 * geo->dst.height;
-       if (geo->dst.height >= 16 * geo->src.height)
-               geo->dst.height = 16 * geo->src.height;
-
-       /* setting scaling ratio */
-       geo->x_ratio = (geo->src.width << 16) / geo->dst.width;
-       geo->y_ratio = (geo->src.height << 16) / geo->dst.height;
-
-       /* adjust offsets */
-       geo->src.x_offset = min(geo->src.x_offset,
-               geo->src.full_width - geo->src.width);
-       geo->src.y_offset = min(geo->src.y_offset,
-               geo->src.full_height - geo->src.height);
-       geo->dst.x_offset = min(geo->dst.x_offset,
-               geo->dst.full_width - geo->dst.width);
-       geo->dst.y_offset = min(geo->dst.y_offset,
-               geo->dst.full_height - geo->dst.height);
+static void mxr_vp_fix_geometry(struct mxr_layer *layer,
+       enum mxr_geometry_stage stage, unsigned long flags)
+{
+       struct mxr_geometry *geo = &layer->geo;
+       struct mxr_crop *src = &geo->src;
+       struct mxr_crop *dst = &geo->dst;
+       unsigned long x_center, y_center;
+
+       switch (stage) {
+
+       case MXR_GEOMETRY_SINK: /* nothing to be fixed here */
+       case MXR_GEOMETRY_COMPOSE:
+               /* remember center of the area */
+               x_center = dst->x_offset + dst->width / 2;
+               y_center = dst->y_offset + dst->height / 2;
+
+               /* ensure that compose is reachable using 16x scaling */
+               dst->width = clamp(dst->width, 8U, 16 * src->full_width);
+               dst->height = clamp(dst->height, 1U, 16 * src->full_height);
+
+               /* setup offsets */
+               dst->x_offset = do_center(x_center, dst->width,
+                       dst->full_width, flags);
+               dst->y_offset = do_center(y_center, dst->height,
+                       dst->full_height, flags);
+               flags = 0; /* remove possible MXR_NO_OFFSET flag */
+               /* fall through */
+       case MXR_GEOMETRY_CROP:
+               /* remember center of the area */
+               x_center = src->x_offset + src->width / 2;
+               y_center = src->y_offset + src->height / 2;
+
+               /* ensure scaling is between 0.25x .. 16x */
+               src->width = clamp(src->width, round_up(dst->width / 16, 4),
+                       dst->width * 4);
+               src->height = clamp(src->height, round_up(dst->height / 16, 4),
+                       dst->height * 4);
+
+               /* hardware limits */
+               src->width = clamp(src->width, 32U, 2047U);
+               src->height = clamp(src->height, 4U, 2047U);
+
+               /* setup offsets */
+               src->x_offset = do_center(x_center, src->width,
+                       src->full_width, flags);
+               src->y_offset = do_center(y_center, src->height,
+                       src->full_height, flags);
+
+               /* setting scaling ratio */
+               geo->x_ratio = (src->width << 16) / dst->width;
+               geo->y_ratio = (src->height << 16) / dst->height;
+               /* fall through */
+
+       case MXR_GEOMETRY_SOURCE:
+               src->full_width = clamp(src->full_width,
+                       ALIGN(src->width + src->x_offset, 8), 8192U);
+               src->full_height = clamp(src->full_height,
+                       src->height + src->y_offset, 8192U);
+       };
 }
 
 /* PUBLIC API */
index 8cec67ef48c9214b0f529039e905de235bca219c..059e7749ce95322962a58c0b411fe33007293a58 100644 (file)
@@ -457,24 +457,4 @@ static struct platform_driver sdo_driver __refdata = {
        }
 };
 
-static int __init sdo_init(void)
-{
-       int ret;
-       static const char banner[] __initdata = KERN_INFO \
-               "Samsung Standard Definition Output (SDO) driver, "
-               "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
-       printk(banner);
-
-       ret = platform_driver_register(&sdo_driver);
-       if (ret)
-               printk(KERN_ERR "SDO platform driver register failed\n");
-
-       return ret;
-}
-module_init(sdo_init);
-
-static void __exit sdo_exit(void)
-{
-       platform_driver_unregister(&sdo_driver);
-}
-module_exit(sdo_exit);
+module_platform_driver(sdo_driver);
index 0f9fb99adeb4e06224445f42d25546038b0bf878..065d0f6be4a061121eed47c5956ad5953980383b 100644 (file)
@@ -5691,6 +5691,27 @@ struct saa7134_board saa7134_boards[] = {
                        .amux = LINE1,
                },
        },
+       [SAA7134_BOARD_SENSORAY811_911] = {
+               .name           = "Sensoray 811/911",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_comp3,
+                       .vmux   = 2,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+       },
 
 };
 
@@ -6913,6 +6934,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x17de,
                .subdevice    = 0xd136,
                .driver_data  = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x6000,
+               .subdevice    = 0x0811,
+               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x6000,
+               .subdevice    = 0x0911,
+               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
        }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
index ca65cda3e101880d63b1c002412af0f80a6561a2..5fbb4e49495c8278f25da91b4dca454c405e5dc0 100644 (file)
@@ -1263,7 +1263,6 @@ static int saa7134_resume(struct pci_dev *pci_dev)
        saa7134_tvaudio_setmute(dev);
        saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
        saa7134_tvaudio_init(dev);
-       saa7134_tvaudio_do_scan(dev);
        saa7134_enable_i2s(dev);
        saa7134_hw_enable2(dev);
 
index 1e4ef16698879f5904fd7b378a4883f48b987640..089fa0fb5c94d359c1a91ce9c5b2630a209a0991 100644 (file)
@@ -183,9 +183,9 @@ static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
-                                          struct dvb_frontend_parameters* params)
+static int mt352_pinnacle_tuner_set_params(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        u8 off[] = { 0x00, 0xf1};
        u8 on[]  = { 0x00, 0x71};
        struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)};
@@ -196,7 +196,7 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
        /* set frequency (mt2050) */
        f.tuner     = 0;
        f.type      = V4L2_TUNER_DIGITAL_TV;
-       f.frequency = params->frequency / 1000 * 16 / 1000;
+       f.frequency = c->frequency / 1000 * 16 / 1000;
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
@@ -287,8 +287,9 @@ static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
  * these tuners are tu1216, td1316(a)
  */
 
-static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda6651_pll_set(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct saa7134_dev *dev = fe->dvb->priv;
        struct tda1004x_state *state = fe->demodulator_priv;
        u8 addr = state->config->tuner_address;
@@ -299,7 +300,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        u8 band, cp, filter;
 
        /* determine charge pump */
-       tuner_frequency = params->frequency + 36166000;
+       tuner_frequency = c->frequency + 36166000;
        if (tuner_frequency < 87000000)
                return -EINVAL;
        else if (tuner_frequency < 130000000)
@@ -324,28 +325,28 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
                return -EINVAL;
 
        /* determine band */
-       if (params->frequency < 49000000)
+       if (c->frequency < 49000000)
                return -EINVAL;
-       else if (params->frequency < 161000000)
+       else if (c->frequency < 161000000)
                band = 1;
-       else if (params->frequency < 444000000)
+       else if (c->frequency < 444000000)
                band = 2;
-       else if (params->frequency < 861000000)
+       else if (c->frequency < 861000000)
                band = 4;
        else
                return -EINVAL;
 
        /* setup PLL filter */
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
+       switch (c->bandwidth_hz) {
+       case 6000000:
                filter = 0;
                break;
 
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                filter = 0;
                break;
 
-       case BANDWIDTH_8_MHZ:
+       case 8000000:
                filter = 1;
                break;
 
@@ -356,7 +357,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        /* calculate divisor
         * ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
         */
-       tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
+       tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
 
        /* setup tuner buffer */
        tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
@@ -436,9 +437,9 @@ static int philips_td1316_tuner_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_td1316_tuner_set_params(struct dvb_frontend *fe)
 {
-       return philips_tda6651_pll_set(fe, params);
+       return philips_tda6651_pll_set(fe);
 }
 
 static int philips_td1316_tuner_sleep(struct dvb_frontend *fe)
index d4ee24bf692820dd0f58004d480d010d1be18c29..22ecd7297d2d3d8465e66336ce1a081408b00cff 100644 (file)
@@ -235,22 +235,25 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 
 static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
-       unsigned char buf[5], cod4, code3, code4;
+       unsigned char buf[5];
 
        /* poll IR chip */
        if (5 != i2c_master_recv(ir->c, buf, 5))
                return -EIO;
 
-       cod4    = buf[4];
-       code4   = (cod4 >> 2);
-       code3   = buf[3];
-       if (code3 == 0)
-               /* no key pressed */
+       /* Check if some key were pressed */
+       if (!(buf[0] & 0x80))
                return 0;
 
-       /* return key */
-       *ir_key = code4;
-       *ir_raw = code4;
+       /*
+        * buf[3] & 0x80 is always high.
+        * buf[3] & 0x40 is a parity bit. A repeat event is marked
+        * by preserving it into two separate readings
+        * buf[4] bits 0 and 1, and buf[1] and buf[2] are always
+        * zero.
+        */
+       *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
+       *ir_raw = *ir_key;
        return 1;
 }
 
@@ -752,7 +755,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                polling      = 50; /* ms */
                break;
        case SAA7134_BOARD_VIDEOMATE_M1F:
-               ir_codes     = RC_MAP_VIDEOMATE_M1F;
+               ir_codes     = RC_MAP_VIDEOMATE_K100;
                mask_keycode = 0x0ff00;
                mask_keyup   = 0x040000;
                break;
index 57e646bb48b394008e42b686922dc3233554fb9f..b7a99bee2f98b404abbb398e3db48131ca132b64 100644 (file)
@@ -332,6 +332,13 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
 {
        __s32 left,right,value;
 
+       if (!(dev->tvnorm->id & scan->std)) {
+               value = 0;
+               dprintk("skipping %d.%03d MHz [%4s]\n",
+                       scan->carr / 1000, scan->carr % 1000, scan->name);
+               return 0;
+       }
+
        if (audio_debug > 1) {
                int i;
                dprintk("debug %d:",scan->carr);
@@ -348,30 +355,25 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
                }
                printk("\n");
        }
-       if (dev->tvnorm->id & scan->std) {
-               tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
-               saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-               if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-                       return -1;
-               left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-               tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
-               saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-               if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-                       return -1;
-               right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-               left >>= 16;
-               right >>= 16;
-               value = left > right ? left - right : right - left;
-               dprintk("scanning %d.%03d MHz [%4s] =>  dc is %5d [%d/%d]\n",
-                       scan->carr / 1000, scan->carr % 1000,
-                       scan->name, value, left, right);
-       } else {
-               value = 0;
-               dprintk("skipping %d.%03d MHz [%4s]\n",
-                       scan->carr / 1000, scan->carr % 1000, scan->name);
-       }
+
+       tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
+       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+               return -1;
+       left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+       tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
+       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+               return -1;
+       right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+       left >>= 16;
+       right >>= 16;
+       value = left > right ? left - right : right - left;
+       dprintk("scanning %d.%03d MHz [%4s] =>  dc is %5d [%d/%d]\n",
+               scan->carr / 1000, scan->carr % 1000,
+               scan->name, value, left, right);
        return value;
 }
 
@@ -546,6 +548,7 @@ static int tvaudio_thread(void *data)
                                dev->tvnorm->name, carrier/1000, carrier%1000,
                                max1, max2);
                        dev->last_carrier = carrier;
+                       dev->automute = 0;
 
                } else if (0 != dev->last_carrier) {
                        /* no carrier -- try last detected one as fallback */
@@ -553,6 +556,7 @@ static int tvaudio_thread(void *data)
                        dprintk("audio carrier scan failed, "
                                "using %d.%03d MHz [last detected]\n",
                                carrier/1000, carrier%1000);
+                       dev->automute = 1;
 
                } else {
                        /* no carrier + no fallback -- use default */
@@ -560,9 +564,9 @@ static int tvaudio_thread(void *data)
                        dprintk("audio carrier scan failed, "
                                "using %d.%03d MHz [default]\n",
                                carrier/1000, carrier%1000);
+                       dev->automute = 1;
                }
                tvaudio_setcarrier(dev,carrier,carrier);
-               dev->automute = 0;
                saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
                saa7134_tvaudio_setmute(dev);
                /* find the exact tv audio norm */
@@ -601,7 +605,7 @@ static int tvaudio_thread(void *data)
                        if (kthread_should_stop())
                                break;
                        if (UNSET == dev->thread.mode) {
-                               rx = tvaudio_getstereo(dev,&tvaudio[i]);
+                               rx = tvaudio_getstereo(dev, &tvaudio[audio]);
                                mode = saa7134_tvaudio_rx2mode(rx);
                        } else {
                                mode = dev->thread.mode;
@@ -1020,6 +1024,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
        }
 
        dev->thread.thread = NULL;
+       dev->thread.scan1 = dev->thread.scan2 = 0;
        if (my_thread) {
                saa7134_tvaudio_init(dev);
                /* start tvaudio thread */
@@ -1029,13 +1034,19 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
                               dev->name);
                        /* XXX: missing error handling here */
                }
-               saa7134_tvaudio_do_scan(dev);
        }
 
        saa7134_enable_i2s(dev);
        return 0;
 }
 
+int saa7134_tvaudio_close(struct saa7134_dev *dev)
+{
+       dev->automute = 1;
+       /* anything else to undo? */
+       return 0;
+}
+
 int saa7134_tvaudio_fini(struct saa7134_dev *dev)
 {
        /* shutdown tvaudio thread */
index 9cf7914f6f90eb87c03205650a39396a50b84f38..417034eb6ad258d55cfe10dc0d160e00b9a6130f 100644 (file)
@@ -1462,6 +1462,8 @@ static int video_release(struct file *file)
        struct saa6588_command cmd;
        unsigned long flags;
 
+       saa7134_tvaudio_close(dev);
+
        /* turn off overlay */
        if (res_check(fh, RESOURCE_OVERLAY)) {
                spin_lock_irqsave(&dev->slock,flags);
index 9b550687213a44c7b808ca73bfa6713e05aebb50..42fba4f93c72b95cf1429f2e846b0b608ac2c77b 100644 (file)
@@ -330,6 +330,7 @@ struct saa7134_card_ir {
 #define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185
 #define SAA7134_BOARD_BEHOLD_501            186
 #define SAA7134_BOARD_BEHOLD_503FM          187
+#define SAA7134_BOARD_SENSORAY811_911       188
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
@@ -817,6 +818,7 @@ void saa7134_tvaudio_init(struct saa7134_dev *dev);
 int saa7134_tvaudio_init2(struct saa7134_dev *dev);
 int saa7134_tvaudio_fini(struct saa7134_dev *dev);
 int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
+int saa7134_tvaudio_close(struct saa7134_dev *dev);
 
 int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
 
index 466e1b02f91f42c38c9a8af77d0eb1f9794c55f5..a7f58a9987522c06a45dfcaf3f45ab138f8c3699 100644 (file)
@@ -149,7 +149,7 @@ int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
        saa7164_bus_verify(dev);
 
        msg->size = cpu_to_le16(msg->size);
-       msg->command = cpu_to_le16(msg->command);
+       msg->command = cpu_to_le32(msg->command);
        msg->controlselector = cpu_to_le16(msg->controlselector);
 
        if (msg->size > dev->bus.m_wMaxReqSize) {
@@ -464,7 +464,7 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
 
 peekout:
        msg->size = le16_to_cpu(msg->size);
-       msg->command = le16_to_cpu(msg->command);
+       msg->command = le32_to_cpu(msg->command);
        msg->controlselector = le16_to_cpu(msg->controlselector);
        ret = SAA_OK;
 out:
index c51decfcae197cedb83f6d68169cc0a6251f621d..f854d85a387c0956a6cf4caf349ff9a5af056377 100644 (file)
@@ -786,8 +786,7 @@ static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev,
                V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 /* Capture is not running, no interrupts, no locking needed */
-static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
-                                      __u32 pixfmt)
+static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -925,11 +924,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        ceu_write(pcdev, CDOCR, value);
        ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
 
-       dev_dbg(icd->parent, "S_FMT successful for %c%c%c%c %ux%u\n",
-               pixfmt & 0xff, (pixfmt >> 8) & 0xff,
-               (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff,
-               icd->user_width, icd->user_height);
-
        capture_restore(pcdev, capsr);
 
        /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */
@@ -1966,8 +1960,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
                if (!ret) {
                        icd->user_width         = out_width & ~3;
                        icd->user_height        = out_height & ~3;
-                       ret = sh_mobile_ceu_set_bus_param(icd,
-                                       icd->current_fmt->host_fmt->fourcc);
+                       ret = sh_mobile_ceu_set_bus_param(icd);
                }
        }
 
index 8a652b53ff7e9a8a1a4ad0f00bf7a874bf8f3bf6..05286500b4d432de590fa206070c2611bcb57a5a 100644 (file)
@@ -390,18 +390,7 @@ static struct platform_driver __refdata sh_csi2_pdrv = {
        },
 };
 
-static int __init sh_csi2_init(void)
-{
-       return platform_driver_register(&sh_csi2_pdrv);
-}
-
-static void __exit sh_csi2_exit(void)
-{
-       platform_driver_unregister(&sh_csi2_pdrv);
-}
-
-module_init(sh_csi2_init);
-module_exit(sh_csi2_exit);
+module_platform_driver(sh_csi2_pdrv);
 
 MODULE_DESCRIPTION("SH-Mobile MIPI CSI-2 driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
index 62e4312515cb99a5e640cfe440954f1b8f5994cd..b82710745ba8b40fdd3b3f7f1326050541eacad8 100644 (file)
@@ -487,7 +487,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
                icd->user_width, icd->user_height);
 
        /* set physical bus parameters */
-       return ici->ops->set_bus_param(icd, pix->pixelformat);
+       return ici->ops->set_bus_param(icd);
 }
 
 static int soc_camera_open(struct file *file)
@@ -600,9 +600,9 @@ static int soc_camera_close(struct file *file)
                pm_runtime_suspend(&icd->vdev->dev);
                pm_runtime_disable(&icd->vdev->dev);
 
-               ici->ops->remove(icd);
                if (ici->ops->init_videobuf2)
                        vb2_queue_release(&icd->vb2_vidq);
+               ici->ops->remove(icd);
 
                soc_camera_power_off(icd, icl);
        }
index 4402a8a74f7a727fc7dd87492a98b5c8ad426d7a..f59ccade07c8b5cb9a0c3ebb4c4bdb539e2cbea8 100644 (file)
@@ -189,18 +189,7 @@ static struct platform_driver soc_camera_platform_driver = {
        .remove         = soc_camera_platform_remove,
 };
 
-static int __init soc_camera_platform_module_init(void)
-{
-       return platform_driver_register(&soc_camera_platform_driver);
-}
-
-static void __exit soc_camera_platform_module_exit(void)
-{
-       platform_driver_unregister(&soc_camera_platform_driver);
-}
-
-module_init(soc_camera_platform_module_init);
-module_exit(soc_camera_platform_module_exit);
+module_platform_driver(soc_camera_platform_driver);
 
 MODULE_DESCRIPTION("SoC Camera Platform driver");
 MODULE_AUTHOR("Magnus Damm");
index 3c61aec517ac3d4edcd6ea1a07a5c36dc9bd6f46..d427f8436c70468721140d655eb00196d9ccf80b 100644 (file)
@@ -377,8 +377,8 @@ static int stk_prepare_iso(struct stk_camera *dev)
        if (dev->isobufs)
                STK_ERROR("isobufs already allocated. Bad\n");
        else
-               dev->isobufs = kzalloc(MAX_ISO_BUFS * sizeof(*dev->isobufs),
-                                       GFP_KERNEL);
+               dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs),
+                                      GFP_KERNEL);
        if (dev->isobufs == NULL) {
                STK_ERROR("Unable to allocate iso buffers\n");
                return -ENOMEM;
index a0895bf07487847c921505e7d119dfa434c40037..0a2d75f0406631f582b17b50aaf6c4cd11e074df 100644 (file)
@@ -872,20 +872,7 @@ static struct platform_driver timblogiw_platform_driver = {
        .remove         = __devexit_p(timblogiw_remove),
 };
 
-/* Module functions */
-
-static int __init timblogiw_init(void)
-{
-       return platform_driver_register(&timblogiw_platform_driver);
-}
-
-static void __exit timblogiw_exit(void)
-{
-       platform_driver_unregister(&timblogiw_platform_driver);
-}
-
-module_init(timblogiw_init);
-module_exit(timblogiw_exit);
+module_platform_driver(timblogiw_platform_driver);
 
 MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
 MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
index 56564e6aaac2b60c19238604607499011d68ba58..5dd73b7857d12087a7689c4d4dbe81bce77c3c6e 100644 (file)
@@ -140,7 +140,7 @@ struct pd_dvb_adapter {
        u8                      reserved[3];
 
        /* data for power resume*/
-       struct dvb_frontend_parameters fe_param;
+       struct dtv_frontend_properties fe_param;
 
        /* for channel scanning */
        int             prev_freq;
index d0da11ae19dfe5cd4d218975db4b3de0747a41a8..30fcb117e89899a25208428061900d22eefb829c 100644 (file)
@@ -12,9 +12,9 @@
 static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
 
 static int dvb_bandwidth[][2] = {
-       { TLG_BW_8, BANDWIDTH_8_MHZ },
-       { TLG_BW_7, BANDWIDTH_7_MHZ },
-       { TLG_BW_6, BANDWIDTH_6_MHZ }
+       { TLG_BW_8, 8000000 },
+       { TLG_BW_7, 7000000 },
+       { TLG_BW_6, 6000000 }
 };
 static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
 
@@ -146,9 +146,9 @@ static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
        return msec > 800 ? true : false;
 }
 
-static int poseidon_set_fe(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *fep)
+static int poseidon_set_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        s32 ret = 0, cmd_status = 0;
        s32 i, bandwidth = -1;
        struct poseidon *pd = fe->demodulator_priv;
@@ -159,7 +159,7 @@ static int poseidon_set_fe(struct dvb_frontend *fe,
 
        mutex_lock(&pd->lock);
        for (i = 0; i < dvb_bandwidth_length; i++)
-               if (fep->u.ofdm.bandwidth == dvb_bandwidth[i][1])
+               if (fep->bandwidth_hz == dvb_bandwidth[i][1])
                        bandwidth = dvb_bandwidth[i][0];
 
        if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
@@ -210,7 +210,7 @@ static int pm_dvb_resume(struct poseidon *pd)
 
        poseidon_check_mode_dvbt(pd);
        msleep(300);
-       poseidon_set_fe(&pd_dvb->dvb_fe, &pd_dvb->fe_param);
+       poseidon_set_fe(&pd_dvb->dvb_fe);
 
        dvb_start_streaming(pd_dvb);
        return 0;
@@ -227,13 +227,13 @@ static s32 poseidon_fe_init(struct dvb_frontend *fe)
        pd->pm_resume  = pm_dvb_resume;
 #endif
        memset(&pd_dvb->fe_param, 0,
-                       sizeof(struct dvb_frontend_parameters));
+                       sizeof(struct dtv_frontend_properties));
        return 0;
 }
 
-static int poseidon_get_fe(struct dvb_frontend *fe,
-                       struct dvb_frontend_parameters *fep)
+static int poseidon_get_fe(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct poseidon *pd = fe->demodulator_priv;
        struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
 
@@ -332,9 +332,9 @@ static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
 }
 
 static struct dvb_frontend_ops poseidon_frontend_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name           = "Poseidon DVB-T",
-               .type           = FE_OFDM,
                .frequency_min  = 174000000,
                .frequency_max  = 862000000,
                .frequency_stepsize       = 62500,/* FIXME */
index 114eec8a630a62f8610b7f9df8e7254c55e583e4..a43b77abd931996199ec83c49734e8a3afefa652 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_TM6000
        tristate "TV Master TM5600/6000/6010 driver"
-       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
+       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB
        select VIDEO_TUNER
        select MEDIA_TUNER_XC2028
        select MEDIA_TUNER_XC5000
@@ -16,7 +16,7 @@ config VIDEO_TM6000
 
 config VIDEO_TM6000_ALSA
        tristate "TV Master TM5600/6000/6010 audio support"
-       depends on VIDEO_TM6000 && SND && EXPERIMENTAL
+       depends on VIDEO_TM6000 && SND
        select SND_PCM
        ---help---
          This is a video4linux driver for direct (DMA) audio for
@@ -27,7 +27,7 @@ config VIDEO_TM6000_ALSA
 
 config VIDEO_TM6000_DVB
        tristate "DVB Support for tm6000 based TV cards"
-       depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL
+       depends on VIDEO_TM6000 && DVB_CORE && USB
        select DVB_ZL10353
        ---help---
          This adds support for DVB cards based on the tm5600/tm6000 chip.
index bb2047c1035898cf63248bf6e7ca975992b3ba76..bd07ec707956d377eae03f3278fa8972e8cf4972 100644 (file)
@@ -146,20 +146,21 @@ static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
 #define DEFAULT_FIFO_SIZE      4096
 
 static struct snd_pcm_hardware snd_tm6000_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP |
+       .info = SNDRV_PCM_INFO_BATCH |
+               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_CONTINUOUS,
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
        .rate_min = 48000,
        .rate_max = 48000,
        .channels_min = 2,
        .channels_max = 2,
        .period_bytes_min = 64,
        .period_bytes_max = 12544,
-       .periods_min = 1,
+       .periods_min = 2,
        .periods_max = 98,
        .buffer_bytes_max = 62720 * 8,
 };
@@ -181,6 +182,7 @@ static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
        chip->substream = substream;
 
        runtime->hw = snd_tm6000_digital_hw;
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
 
        return 0;
 _error:
@@ -347,9 +349,13 @@ static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
        int err = 0;
 
        switch (cmd) {
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
        case SNDRV_PCM_TRIGGER_START:
                atomic_set(&core->stream_started, 1);
                break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
        case SNDRV_PCM_TRIGGER_STOP:
                atomic_set(&core->stream_started, 0);
                break;
@@ -371,6 +377,14 @@ static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
        return chip->buf_pos;
 }
 
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
 /*
  * operators
  */
@@ -383,6 +397,7 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = {
        .prepare = snd_tm6000_prepare,
        .trigger = snd_tm6000_card_trigger,
        .pointer = snd_tm6000_pointer,
+       .page = snd_pcm_get_vmalloc_page,
 };
 
 /*
index ff939bc0e0b997adc0b41f0fc8c0bffa24a1edcc..034659b1317480a3c389ff9619dd3123c9aeb39d 100644 (file)
@@ -351,6 +351,7 @@ static struct tm6000_board tm6000_boards[] = {
                .tuner_addr   = 0xc2 >> 1,
                .demod_addr   = 0x1e >> 1,
                .type         = TM6010,
+               .ir_codes = RC_MAP_HAUPPAUGE,
                .caps = {
                        .has_tuner    = 1,
                        .has_dvb      = 1,
@@ -639,6 +640,7 @@ static struct usb_device_id tm6000_id_table[] = {
        { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
        { }
 };
+MODULE_DEVICE_TABLE(usb, tm6000_id_table);
 
 /* Control power led for show some activity */
 void tm6000_flash_led(struct tm6000_core *dev, u8 state)
@@ -941,6 +943,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
                case TM6010_BOARD_HAUPPAUGE_900H:
                case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
                case TM6010_BOARD_TWINHAN_TU501:
+                       ctl.max_len = 80;
                        ctl.fname = "xc3028L-v36.fw";
                        break;
                default:
@@ -1002,6 +1005,7 @@ static int fill_board_specific_data(struct tm6000_core *dev)
        /* setup per-model quirks */
        switch (dev->model) {
        case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+       case TM6010_BOARD_HAUPPAUGE_900H:
                dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
                break;
 
@@ -1050,6 +1054,33 @@ static void use_alternative_detection_method(struct tm6000_core *dev)
               tm6000_boards[model].name, model);
 }
 
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct tm6000_core *dev = container_of(work, struct tm6000_core,
+                                              request_module_wk);
+
+       request_module("tm6000-alsa");
+
+       if (dev->caps.has_dvb)
+               request_module("tm6000-dvb");
+}
+
+static void request_modules(struct tm6000_core *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct tm6000_core *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
 static int tm6000_init_dev(struct tm6000_core *dev)
 {
        struct v4l2_frequency f;
@@ -1112,6 +1143,8 @@ static int tm6000_init_dev(struct tm6000_core *dev)
 
        tm6000_ir_init(dev);
 
+       request_modules(dev);
+
        mutex_unlock(&dev->lock);
        return 0;
 
@@ -1324,6 +1357,8 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
 
        printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
 
+       flush_request_modules(dev);
+
        tm6000_ir_fini(dev);
 
        if (dev->gpio.power_led) {
index 9783616a0da2791b83680132168d1522baf8b9af..22cc0116deb65e9f9e26f8b2ba844c778d6a5c57 100644 (file)
@@ -38,6 +38,7 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
        int          ret, i;
        unsigned int pipe;
        u8           *data = NULL;
+       int delay = 5000;
 
        mutex_lock(&dev->usb_lock);
 
@@ -88,7 +89,20 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
        }
 
        kfree(data);
-       msleep(5);
+
+       if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
+               delay = 0;
+
+       if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
+               unsigned int tsleep;
+               /* Calculate delay time, 14000us for 64 bytes */
+               tsleep = (len * 200) + 200;
+               if (tsleep < delay)
+                       tsleep = delay;
+               usleep_range(tsleep, tsleep + 1000);
+       }
+       else if (delay)
+               usleep_range(delay, delay + 1000);
 
        mutex_unlock(&dev->usb_lock);
        return ret;
@@ -125,14 +139,14 @@ int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
        u8 new_index;
 
        rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 1);
+                                       value, 0, buf, 1);
 
        if (rc < 0)
                return rc;
 
        new_index = (buf[0] & ~mask) | (index & mask);
 
-       if (new_index == index)
+       if (new_index == buf[0])
                return 0;
 
        return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
@@ -536,16 +550,16 @@ static struct reg_init tm6010_init_tab[] = {
 
        { TM6010_REQ05_R18_IMASK7, 0x00 },
 
-       { TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
-       { TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
-       { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
-       { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
+       { TM6010_REQ07_RDC_IR_LEADER1, 0xaa },
+       { TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
+       { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
+       { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
        { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
-       { TM6010_REQ07_RD8_IR, 0x2f },
+       { TM6010_REQ07_RD8_IR, 0x0f },
 
        /* set remote wakeup key:any key wakeup */
        { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
-       { TM6010_REQ07_RD8_IR_WAKEUP_SEL,  0xff },
+       { TM6010_REQ07_RDA_IR_WAKEUP_SEL,  0xff },
 };
 
 int tm6000_init(struct tm6000_core *dev)
@@ -599,55 +613,6 @@ int tm6000_init(struct tm6000_core *dev)
        return rc;
 }
 
-int tm6000_reset(struct tm6000_core *dev)
-{
-       int pipe;
-       int err;
-
-       msleep(500);
-
-       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
-       if (err < 0) {
-               tm6000_err("failed to select interface %d, alt. setting 0\n",
-                               dev->isoc_in.bInterfaceNumber);
-               return err;
-       }
-
-       err = usb_reset_configuration(dev->udev);
-       if (err < 0) {
-               tm6000_err("failed to reset configuration\n");
-               return err;
-       }
-
-       if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
-               msleep(5);
-
-       /*
-        * Not all devices have int_in defined
-        */
-       if (!dev->int_in.endp)
-               return 0;
-
-       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
-       if (err < 0) {
-               tm6000_err("failed to select interface %d, alt. setting 2\n",
-                               dev->isoc_in.bInterfaceNumber);
-               return err;
-       }
-
-       msleep(5);
-
-       pipe = usb_rcvintpipe(dev->udev,
-                       dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-
-       err = usb_clear_halt(dev->udev, pipe);
-       if (err < 0) {
-               tm6000_err("usb_clear_halt failed: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
 
 int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
 {
@@ -696,11 +661,13 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev)
        if (dev->dev_type == TM6010) {
                /* Audio crossbar setting, default SIF1 */
                u8 areg_f0;
+               u8 areg_07 = 0x10;
 
                switch (dev->rinput.amux) {
                case TM6000_AMUX_SIF1:
                case TM6000_AMUX_SIF2:
                        areg_f0 = 0x03;
+                       areg_07 = 0x30;
                        break;
                case TM6000_AMUX_ADC1:
                        areg_f0 = 0x00;
@@ -720,6 +687,9 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev)
                /* Set audio input crossbar */
                tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
                                                        areg_f0, 0x0f);
+               /* Mux overflow workaround */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                       areg_07, 0xf0);
        } else {
                u8 areg_eb;
                /* Audio setting, default LINE1 */
index 5e6c129a4bebd2564f18779be0051573fa9b9242..e1f3f66e1e63018f3db3074bfb276f765808dc96 100644 (file)
@@ -89,9 +89,19 @@ static void tm6000_urb_received(struct urb *urb)
        int ret;
        struct tm6000_core *dev = urb->context;
 
-       if (urb->status != 0)
+       switch (urb->status) {
+       case 0:
+       case -ETIMEDOUT:
+               break;
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               return;
+       default:
                print_err_status(dev, 0, urb->status);
-       else if (urb->actual_length > 0)
+       }
+
+       if (urb->actual_length > 0)
                dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
                                                   urb->actual_length);
 
@@ -151,7 +161,7 @@ static int tm6000_start_stream(struct tm6000_core *dev)
                printk(KERN_ERR "tm6000: pipe resetted\n");
 
 /*     mutex_lock(&tm6000_driver.open_close_mutex); */
-       ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
+       ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
 
 /*     mutex_unlock(&tm6000_driver.open_close_mutex); */
        if (ret) {
@@ -396,6 +406,11 @@ static int dvb_init(struct tm6000_core *dev)
        if (!dev->caps.has_dvb)
                return 0;
 
+       if (dev->udev->speed == USB_SPEED_FULL) {
+               printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
+               return 0;
+       }
+
        dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
        if (!dvb) {
                printk(KERN_INFO "Cannot allocate memory\n");
index 0290bbf00c3e68c0541e87803d98963b721e8a41..c7e23e3dd75ed4f47276ace2f8480b461a9131fe 100644 (file)
@@ -46,11 +46,10 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
                                __u8 reg, char *buf, int len)
 {
        int rc;
-       unsigned int tsleep;
        unsigned int i2c_packet_limit = 16;
 
        if (dev->dev_type == TM6010)
-               i2c_packet_limit = 64;
+               i2c_packet_limit = 80;
 
        if (!buf)
                return -1;
@@ -71,10 +70,6 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
                return rc;
        }
 
-       /* Calculate delay time, 14000us for 64 bytes */
-       tsleep = ((len * 200) + 200 + 1000) / 1000;
-       msleep(tsleep);
-
        /* release mutex */
        return rc;
 }
@@ -145,7 +140,6 @@ static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
                        return rc;
                }
 
-               msleep(1400 / 1000);
                rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
                        USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
                        reg, 0, buf, len);
index 405d12729d057c0d6eebce12d5614f266c3211a8..7844607dd45adac97646a08aaf3bcdfc74bbd2f6 100644 (file)
 
 static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
+MODULE_PARM_DESC(ir_debug, "debug message level");
 
 static unsigned int enable_ir = 1;
 module_param(enable_ir, int, 0644);
 MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
 
-/* number of 50ms for ON-OFF-ON power led */
-/* show IR activity */
-#define PWLED_OFF 2
+static unsigned int ir_clock_mhz = 12;
+module_param(ir_clock_mhz, int, 0644);
+MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
+
+#define URB_SUBMIT_DELAY       100     /* ms - Delay to submit an URB request on retrial and init */
+#define URB_INT_LED_DELAY      100     /* ms - Delay to turn led on again on int mode */
 
 #undef dprintk
 
-#define dprintk(fmt, arg...) \
-       if (ir_debug) { \
+#define dprintk(level, fmt, arg...) do {\
+       if (ir_debug >= level) \
                printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-       }
+       } while (0)
 
 struct tm6000_ir_poll_result {
        u16 rc_data;
@@ -62,20 +65,15 @@ struct tm6000_IR {
        int                     polling;
        struct delayed_work     work;
        u8                      wait:1;
-       u8                      key:1;
-       u8                      pwled:1;
-       u8                      pwledcnt;
+       u8                      pwled:2;
+       u8                      submit_urb:1;
        u16                     key_addr;
        struct urb              *int_urb;
-       u8                      *urb_data;
-
-       int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
 
        /* IR device properties */
        u64                     rc_type;
 };
 
-
 void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
 {
        struct tm6000_IR *ir = dev->ir;
@@ -83,62 +81,84 @@ void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
        if (!dev->ir)
                return;
 
+       dprintk(2, "%s: %i\n",__func__, ir->wait);
+
        if (state)
                ir->wait = 1;
        else
                ir->wait = 0;
 }
 
-
 static int tm6000_ir_config(struct tm6000_IR *ir)
 {
        struct tm6000_core *dev = ir->dev;
-       u8 buf[10];
-       int rc;
+       u32 pulse = 0, leader = 0;
+
+       dprintk(2, "%s\n",__func__);
+
+       /*
+        * The IR decoder supports RC-5 or NEC, with a configurable timing.
+        * The timing configuration there is not that accurate, as it uses
+        * approximate values. The NEC spec mentions a 562.5 unit period,
+        * and RC-5 uses a 888.8 period.
+        * Currently, driver assumes a clock provided by a 12 MHz XTAL, but
+        * a modprobe parameter can adjust it.
+        * Adjustments are required for other timings.
+        * It seems that the 900ms timing for NEC is used to detect a RC-5
+        * IR, in order to discard such decoding
+        */
 
        switch (ir->rc_type) {
        case RC_TYPE_NEC:
-               /* Setup IR decoder for NEC standard 12MHz system clock */
-               /* IR_LEADER_CNT = 0.9ms             */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
-               /* IR_PULSE_CNT = 0.7ms              */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
-               /* Remote WAKEUP = enable */
-               tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
-               /* IR_WKUP_SEL = Low byte in decoded IR data */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
-               /* IR_WKU_ADD code */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
-               tm6000_flash_led(dev, 0);
-               msleep(100);
-               tm6000_flash_led(dev, 1);
+               leader = 900;   /* ms */
+               pulse  = 700;   /* ms - the actual value would be 562 */
                break;
        default:
-               /* hack */
-               buf[0] = 0xff;
-               buf[1] = 0xff;
-               buf[2] = 0xf2;
-               buf[3] = 0x2b;
-               buf[4] = 0x20;
-               buf[5] = 0x35;
-               buf[6] = 0x60;
-               buf[7] = 0x04;
-               buf[8] = 0xc0;
-               buf[9] = 0x08;
-
-               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
-               msleep(100);
-
-               if (rc < 0) {
-                       printk(KERN_INFO "IR configuration failed");
-                       return rc;
-               }
+       case RC_TYPE_RC5:
+               leader = 900;   /* ms - from the NEC decoding */
+               pulse  = 1780;  /* ms - The actual value would be 1776 */
                break;
        }
 
+       pulse = ir_clock_mhz * pulse;
+       leader = ir_clock_mhz * leader;
+       if (ir->rc_type == RC_TYPE_NEC)
+               leader = leader | 0x8000;
+
+       dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
+               __func__,
+               (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+               ir_clock_mhz, leader, pulse);
+
+       /* Remote WAKEUP = enable, normal mode, from IR decoder output */
+       tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+
+       /* Enable IR reception on non-busrt mode */
+       tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
+
+       /* IR_WKUP_SEL = Low byte in decoded IR data */
+       tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
+       /* IR_WKU_ADD code */
+       tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
+
+       tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
+       tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
+
+       tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
+       tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
+
+       if (!ir->polling)
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+       else
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
+       msleep(10);
+
+       /* Shows that IR is working via the LED */
+       tm6000_flash_led(dev, 0);
+       msleep(100);
+       tm6000_flash_led(dev, 1);
+       ir->pwled = 1;
+
        return 0;
 }
 
@@ -146,132 +166,124 @@ static void tm6000_ir_urb_received(struct urb *urb)
 {
        struct tm6000_core *dev = urb->context;
        struct tm6000_IR *ir = dev->ir;
+       struct tm6000_ir_poll_result poll_result;
+       char *buf;
        int rc;
 
-       if (urb->status != 0)
-               printk(KERN_INFO "not ready\n");
-       else if (urb->actual_length > 0) {
-               memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
+       dprintk(2, "%s\n",__func__);
+       if (urb->status < 0 || urb->actual_length <= 0) {
+               printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
+                      urb->status, urb->actual_length);
+               ir->submit_urb = 1;
+               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+               return;
+       }
+       buf = urb->transfer_buffer;
 
-               dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
-                       ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+       if (ir_debug)
+               print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
+                              DUMP_PREFIX_OFFSET,16, 1,
+                              buf, urb->actual_length, false);
 
-               ir->key = 1;
-       }
+       poll_result.rc_data = buf[0];
+       if (urb->actual_length > 1)
+               poll_result.rc_data |= buf[1] << 8;
+
+       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+       rc_keydown(ir->rc, poll_result.rc_data, 0);
 
        rc = usb_submit_urb(urb, GFP_ATOMIC);
+       /*
+        * Flash the led. We can't do it here, as it is running on IRQ context.
+        * So, use the scheduler to do it, in a few ms.
+        */
+       ir->pwled = 2;
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
 }
 
-static int default_polling_getkey(struct tm6000_IR *ir,
-                               struct tm6000_ir_poll_result *poll_result)
+static void tm6000_ir_handle_key(struct work_struct *work)
 {
+       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
        struct tm6000_core *dev = ir->dev;
+       struct tm6000_ir_poll_result poll_result;
        int rc;
        u8 buf[2];
 
-       if (ir->wait && !&dev->int_in)
-               return 0;
-
-       if (&dev->int_in) {
-               switch (ir->rc_type) {
-               case RC_TYPE_RC5:
-                       poll_result->rc_data = ir->urb_data[0];
-                       break;
-               case RC_TYPE_NEC:
-                       if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
-                               poll_result->rc_data = ir->urb_data[0]
-                                                       | ir->urb_data[1] << 8;
-                       }
-                       break;
-               default:
-                       poll_result->rc_data = ir->urb_data[0]
-                                       | ir->urb_data[1] << 8;
-                       break;
-               }
-       } else {
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
-               msleep(10);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
-               msleep(10);
-
-               if (ir->rc_type == RC_TYPE_RC5) {
-                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
-                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               REQ_02_GET_IR_CODE, 0, 0, buf, 1);
-
-                       msleep(10);
-
-                       dprintk("read data=%02x\n", buf[0]);
-                       if (rc < 0)
-                               return rc;
+       if (ir->wait)
+               return;
 
-                       poll_result->rc_data = buf[0];
-               } else {
-                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
-                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+       dprintk(3, "%s\n",__func__);
 
-                       msleep(10);
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+       if (rc < 0)
+               return;
 
-                       dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
-                       if (rc < 0)
-                               return rc;
+       if (rc > 1)
+               poll_result.rc_data = buf[0] | buf[1] << 8;
+       else
+               poll_result.rc_data = buf[0];
 
-                       poll_result->rc_data = buf[0] | buf[1] << 8;
+       /* Check if something was read */
+       if ((poll_result.rc_data & 0xff) == 0xff) {
+               if (!ir->pwled) {
+                       tm6000_flash_led(dev, 1);
+                       ir->pwled = 1;
                }
-               if ((poll_result->rc_data & 0x00ff) != 0xff)
-                       ir->key = 1;
+               return;
        }
-       return 0;
+
+       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+       rc_keydown(ir->rc, poll_result.rc_data, 0);
+       tm6000_flash_led(dev, 0);
+       ir->pwled = 0;
+
+       /* Re-schedule polling */
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
-static void tm6000_ir_handle_key(struct tm6000_IR *ir)
+static void tm6000_ir_int_work(struct work_struct *work)
 {
+       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
        struct tm6000_core *dev = ir->dev;
-       int result;
-       struct tm6000_ir_poll_result poll_result;
+       int rc;
 
-       /* read the registers containing the IR status */
-       result = ir->get_key(ir, &poll_result);
-       if (result < 0) {
-               printk(KERN_INFO "ir->get_key() failed %d\n", result);
-               return;
-       }
+       dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
+               ir->pwled);
 
-       dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
+       if (ir->submit_urb) {
+               dprintk(3, "Resubmit urb\n");
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
 
-       if (ir->pwled) {
-               if (ir->pwledcnt >= PWLED_OFF) {
-                       ir->pwled = 0;
-                       ir->pwledcnt = 0;
-                       tm6000_flash_led(dev, 1);
-               } else
-                       ir->pwledcnt += 1;
+               rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
+               if (rc < 0) {
+                       printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
+                              rc);
+                       /* Retry in 100 ms */
+                       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+                       return;
+               }
+               ir->submit_urb = 0;
        }
 
-       if (ir->key) {
-               rc_keydown(ir->rc, poll_result.rc_data, 0);
-               ir->key = 0;
-               ir->pwled = 1;
-               ir->pwledcnt = 0;
+       /* Led is enabled only if USB submit doesn't fail */
+       if (ir->pwled == 2) {
                tm6000_flash_led(dev, 0);
+               ir->pwled = 0;
+               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
+       } else if (!ir->pwled) {
+               tm6000_flash_led(dev, 1);
+               ir->pwled = 1;
        }
-       return;
-}
-
-static void tm6000_ir_work(struct work_struct *work)
-{
-       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
-
-       tm6000_ir_handle_key(ir);
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
 static int tm6000_ir_start(struct rc_dev *rc)
 {
        struct tm6000_IR *ir = rc->priv;
 
-       INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
+       dprintk(2, "%s\n",__func__);
+
        schedule_delayed_work(&ir->work, 0);
 
        return 0;
@@ -281,6 +293,8 @@ static void tm6000_ir_stop(struct rc_dev *rc)
 {
        struct tm6000_IR *ir = rc->priv;
 
+       dprintk(2, "%s\n",__func__);
+
        cancel_delayed_work_sync(&ir->work);
 }
 
@@ -291,10 +305,11 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        if (!ir)
                return 0;
 
+       dprintk(2, "%s\n",__func__);
+
        if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
                ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
 
-       ir->get_key = default_polling_getkey;
        ir->rc_type = rc_type;
 
        tm6000_ir_config(ir);
@@ -302,17 +317,19 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        return 0;
 }
 
-int tm6000_ir_int_start(struct tm6000_core *dev)
+static int __tm6000_ir_int_start(struct rc_dev *rc)
 {
-       struct tm6000_IR *ir = dev->ir;
+       struct tm6000_IR *ir = rc->priv;
+       struct tm6000_core *dev = ir->dev;
        int pipe, size;
        int err = -ENOMEM;
 
-
        if (!ir)
                return -ENODEV;
 
-       ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+       dprintk(2, "%s\n",__func__);
+
+       ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
        if (!ir->int_urb)
                return -ENOMEM;
 
@@ -321,42 +338,59 @@ int tm6000_ir_int_start(struct tm6000_core *dev)
                & USB_ENDPOINT_NUMBER_MASK);
 
        size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-       dprintk("IR max size: %d\n", size);
+       dprintk(1, "IR max size: %d\n", size);
 
-       ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+       ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
        if (ir->int_urb->transfer_buffer == NULL) {
                usb_free_urb(ir->int_urb);
                return err;
        }
-       dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
+       dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval);
+
        usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
                ir->int_urb->transfer_buffer, size,
                tm6000_ir_urb_received, dev,
                dev->int_in.endp->desc.bInterval);
-       err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
-       if (err) {
-               kfree(ir->int_urb->transfer_buffer);
-               usb_free_urb(ir->int_urb);
-               return err;
-       }
-       ir->urb_data = kzalloc(size, GFP_KERNEL);
+
+       ir->submit_urb = 1;
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
 
        return 0;
 }
 
-void tm6000_ir_int_stop(struct tm6000_core *dev)
+static void __tm6000_ir_int_stop(struct rc_dev *rc)
 {
-       struct tm6000_IR *ir = dev->ir;
+       struct tm6000_IR *ir = rc->priv;
 
-       if (!ir)
+       if (!ir || !ir->int_urb)
                return;
 
+       dprintk(2, "%s\n",__func__);
+
        usb_kill_urb(ir->int_urb);
        kfree(ir->int_urb->transfer_buffer);
        usb_free_urb(ir->int_urb);
        ir->int_urb = NULL;
-       kfree(ir->urb_data);
-       ir->urb_data = NULL;
+}
+
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!ir)
+               return 0;
+
+       return __tm6000_ir_int_start(ir->rc);
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!ir || !ir->rc)
+               return;
+
+       __tm6000_ir_int_stop(ir->rc);
 }
 
 int tm6000_ir_init(struct tm6000_core *dev)
@@ -374,29 +408,36 @@ int tm6000_ir_init(struct tm6000_core *dev)
        if (!dev->ir_codes)
                return 0;
 
-       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
        rc = rc_allocate_device();
        if (!ir || !rc)
                goto out;
 
+       dprintk(2, "%s\n", __func__);
+
        /* record handles to ourself */
        ir->dev = dev;
        dev->ir = ir;
        ir->rc = rc;
 
-       /* input einrichten */
+       /* input setup */
        rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       /* Neded, in order to support NEC remotes with 24 or 32 bits */
+       rc->scanmask = 0xffff;
        rc->priv = ir;
        rc->change_protocol = tm6000_ir_change_protocol;
-       rc->open = tm6000_ir_start;
-       rc->close = tm6000_ir_stop;
+       if (dev->int_in.endp) {
+               rc->open    = __tm6000_ir_int_start;
+               rc->close   = __tm6000_ir_int_stop;
+               INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
+       } else {
+               rc->open  = tm6000_ir_start;
+               rc->close = tm6000_ir_stop;
+               ir->polling = 50;
+               INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
+       }
        rc->driver_type = RC_DRIVER_SCANCODE;
 
-       ir->polling = 50;
-       ir->pwled = 0;
-       ir->pwledcnt = 0;
-
-
        snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
                                                dev->name);
 
@@ -415,15 +456,6 @@ int tm6000_ir_init(struct tm6000_core *dev)
        rc->driver_name = "tm6000";
        rc->dev.parent = &dev->udev->dev;
 
-       if (&dev->int_in) {
-               dprintk("IR over int\n");
-
-               err = tm6000_ir_int_start(dev);
-
-               if (err)
-                       goto out;
-       }
-
        /* ir register */
        err = rc_register_device(rc);
        if (err)
@@ -447,10 +479,19 @@ int tm6000_ir_fini(struct tm6000_core *dev)
        if (!ir)
                return 0;
 
+       dprintk(2, "%s\n",__func__);
+
        rc_unregister_device(ir->rc);
 
-       if (ir->int_urb)
-               tm6000_ir_int_stop(dev);
+       if (!ir->polling)
+               __tm6000_ir_int_stop(ir->rc);
+
+       tm6000_ir_stop(ir->rc);
+
+       /* Turn off the led */
+       tm6000_flash_led(dev, 0);
+       ir->pwled = 0;
+
 
        kfree(ir);
        dev->ir = NULL;
index 7f491b6de9337a22d7bfda621203218712176ac3..a38c251ed57bbe89443158d851052761cc5eb60e 100644 (file)
@@ -284,19 +284,19 @@ enum {
 /* ONLY for TM6010 */
 #define TM6010_REQ07_RD8_IR                            0x07, 0xd8
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_BSIZE                      0x07, 0xd9
+#define TM6010_REQ07_RD9_IR_BSIZE                      0x07, 0xd9
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_SEL                 0x07, 0xda
+#define TM6010_REQ07_RDA_IR_WAKEUP_SEL                 0x07, 0xda
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_ADD                 0x07, 0xdb
+#define TM6010_REQ07_RDB_IR_WAKEUP_ADD                 0x07, 0xdb
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER1                    0x07, 0xdc
+#define TM6010_REQ07_RDC_IR_LEADER1                    0x07, 0xdc
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER0                    0x07, 0xdd
+#define TM6010_REQ07_RDD_IR_LEADER0                    0x07, 0xdd
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT1                 0x07, 0xde
+#define TM6010_REQ07_RDE_IR_PULSE_CNT1                 0x07, 0xde
 /* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT0                 0x07, 0xdf
+#define TM6010_REQ07_RDF_IR_PULSE_CNT0                 0x07, 0xdf
 /* ONLY for TM6010 */
 #define TM6010_REQ07_RE0_DVIDEO_SOURCE                 0x07, 0xe0
 /* ONLY for TM6010 */
index 9a4145dc3d8750d573d5ec286598e625179598c2..9dc0831d813f8332e9d9394dfdc89e0720880365 100644 (file)
@@ -361,82 +361,51 @@ static int tm6000_set_audio_std(struct tm6000_core *dev)
                return 0;
        }
 
-       switch (tm6010_a_mode) {
+       /*
+        * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one
+        * audio standard for each V4L2_STD type.
+        */
+       if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) {
+               areg_05 |= 0x04;
+       } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) {
+               areg_05 |= 0x43;
+       } else if (dev->norm & V4L2_STD_MN) {
+               areg_05 |= 0x22;
+       } else switch (tm6010_a_mode) {
        /* auto */
        case 0:
-               switch (dev->norm) {
-               case V4L2_STD_NTSC_M_KR:
+               if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L)
                        areg_05 |= 0x00;
-                       break;
-               case V4L2_STD_NTSC_M_JP:
-                       areg_05 |= 0x40;
-                       break;
-               case V4L2_STD_NTSC_M:
-               case V4L2_STD_PAL_M:
-               case V4L2_STD_PAL_N:
-                       areg_05 |= 0x20;
-                       break;
-               case V4L2_STD_PAL_Nc:
-                       areg_05 |= 0x60;
-                       break;
-               case V4L2_STD_SECAM_L:
-                       areg_05 |= 0x00;
-                       break;
-               case V4L2_STD_DK:
+               else    /* Other PAL/SECAM standards */
                        areg_05 |= 0x10;
-                       break;
-               }
                break;
        /* A2 */
        case 1:
-               switch (dev->norm) {
-               case V4L2_STD_B:
-               case V4L2_STD_GH:
-                       areg_05 = 0x05;
-                       break;
-               case V4L2_STD_DK:
+               if (dev->norm & V4L2_STD_DK)
                        areg_05 = 0x09;
-                       break;
-               }
+               else
+                       areg_05 = 0x05;
                break;
        /* NICAM */
        case 2:
-               switch (dev->norm) {
-               case V4L2_STD_B:
-               case V4L2_STD_GH:
-                       areg_05 = 0x07;
-                       break;
-               case V4L2_STD_DK:
+               if (dev->norm & V4L2_STD_DK) {
                        areg_05 = 0x06;
-                       break;
-               case V4L2_STD_PAL_I:
+               } else if (dev->norm & V4L2_STD_PAL_I) {
                        areg_05 = 0x08;
-                       break;
-               case V4L2_STD_SECAM_L:
+               } else if (dev->norm & V4L2_STD_SECAM_L) {
                        areg_05 = 0x0a;
                        areg_02 = 0x02;
-                       break;
+               } else {
+                       areg_05 = 0x07;
                }
                nicam_flag = 1;
                break;
        /* other */
        case 3:
-               switch (dev->norm) {
-               /* DK3_A2 */
-               case V4L2_STD_DK:
+               if (dev->norm & V4L2_STD_DK) {
                        areg_05 = 0x0b;
-                       break;
-               /* Korea */
-               case V4L2_STD_NTSC_M_KR:
-                       areg_05 = 0x04;
-                       break;
-               /* EIAJ */
-               case V4L2_STD_NTSC_M_JP:
-                       areg_05 = 0x03;
-                       break;
-               default:
+               } else {
                        areg_05 = 0x02;
-                       break;
                }
                break;
        }
@@ -557,10 +526,16 @@ int tm6000_set_standard(struct tm6000_core *dev)
                case TM6000_AMUX_ADC1:
                        tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
                                0x00, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x10, 0xf0);
                        break;
                case TM6000_AMUX_ADC2:
                        tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
                                0x08, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x10, 0xf0);
                        break;
                case TM6000_AMUX_SIF1:
                        reg_08_e2 |= 0x02;
@@ -570,6 +545,9 @@ int tm6000_set_standard(struct tm6000_core *dev)
                        tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
                        tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
                                0x02, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x30, 0xf0);
                        break;
                case TM6000_AMUX_SIF2:
                        reg_08_e2 |= 0x02;
@@ -579,6 +557,9 @@ int tm6000_set_standard(struct tm6000_core *dev)
                        tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
                        tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
                                0x02, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x30, 0xf0);
                        break;
                default:
                        break;
index 1e5ace0b5d10517f4e36baf81698d2851b459f45..bc13db736e2457e7d89575b8b7c656f3e05a8ce7 100644 (file)
@@ -1605,16 +1605,25 @@ static int tm6000_release(struct file *file)
        res_free(dev, fh);
 
        if (!dev->users) {
-               int err;
-
                tm6000_uninit_isoc(dev);
 
+               /* Stop interrupt USB pipe */
+               tm6000_ir_int_stop(dev);
+
+               usb_reset_configuration(dev->udev);
+
+               if (dev->int_in.endp)
+                       usb_set_interface(dev->udev,
+                                       dev->isoc_in.bInterfaceNumber, 2);
+               else
+                       usb_set_interface(dev->udev,
+                                       dev->isoc_in.bInterfaceNumber, 0);
+
+               /* Start interrupt USB pipe */
+               tm6000_ir_int_start(dev);
+
                if (!fh->radio)
                        videobuf_mmap_free(&fh->vb_vidq);
-
-               err = tm6000_reset(dev);
-               if (err < 0)
-                       dev_err(&vdev->dev, "reset failed: %d\n", err);
        }
 
        kfree(fh);
index 2777e514eff27a8a95fa0d315f7b040c1ff2c8b3..27ba659cfa85610be14ecd957d5e11d9cdb775c0 100644 (file)
@@ -188,6 +188,9 @@ struct tm6000_core {
        /* Device Capabilities*/
        struct tm6000_capabilities      caps;
 
+       /* Used to load alsa/dvb */
+        struct work_struct             request_module_wk;
+
        /* Tuner configuration */
        int                             tuner_type;             /* type of the tuner */
        int                             tuner_addr;             /* tuner address */
index 11cc980b0cd5e7113da25b6b39297de8e33038da..4059ea178c2d95e680e8679319d8aa1c661fa1b1 100644 (file)
@@ -326,6 +326,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
                t->mode_mask = T_RADIO;
                break;
        case TUNER_PHILIPS_FMD1216ME_MK3:
+       case TUNER_PHILIPS_FMD1216MEX_MK3:
                buffer[0] = 0x0b;
                buffer[1] = 0xdc;
                buffer[2] = 0x9c;
index 6abaa16ae136b950657e1086fee643a0f6cc8b50..6be9910a6e24a8fb2f22985701e23e43fdab7c5f 100644 (file)
@@ -703,21 +703,21 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
        /* First tests should be against specific std */
 
        if (std == V4L2_STD_ALL) {
-               fmt = 0;        /* Autodetect mode */
+               fmt = VIDEO_STD_AUTO_SWITCH_BIT;        /* Autodetect mode */
        } else if (std & V4L2_STD_NTSC_443) {
-               fmt = 0xa;
+               fmt = VIDEO_STD_NTSC_4_43_BIT;
        } else if (std & V4L2_STD_PAL_M) {
-               fmt = 0x6;
+               fmt = VIDEO_STD_PAL_M_BIT;
        } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
-               fmt = 0x8;
+               fmt = VIDEO_STD_PAL_COMBINATION_N_BIT;
        } else {
                /* Then, test against generic ones */
                if (std & V4L2_STD_NTSC)
-                       fmt = 0x2;
+                       fmt = VIDEO_STD_NTSC_MJ_BIT;
                else if (std & V4L2_STD_PAL)
-                       fmt = 0x4;
+                       fmt = VIDEO_STD_PAL_BDGHIN_BIT;
                else if (std & V4L2_STD_SECAM)
-                       fmt = 0xc;
+                       fmt = VIDEO_STD_SECAM_BIT;
        }
 
        v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt);
@@ -779,6 +779,70 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
        return -EINVAL;
 }
 
+static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+{
+       int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
+
+       switch (val & 0x0F) {
+       case 0x01:
+               return V4L2_STD_NTSC;
+       case 0x03:
+               return V4L2_STD_PAL;
+       case 0x05:
+               return V4L2_STD_PAL_M;
+       case 0x07:
+               return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
+       case 0x09:
+               return V4L2_STD_NTSC_443;
+       case 0xb:
+               return V4L2_STD_SECAM;
+       default:
+               return V4L2_STD_UNKNOWN;
+       }
+}
+
+static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+                                               enum v4l2_mbus_pixelcode *code)
+{
+       if (index)
+               return -EINVAL;
+
+       *code = V4L2_MBUS_FMT_YUYV8_2X8;
+       return 0;
+}
+
+static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
+                           struct v4l2_mbus_framefmt *f)
+{
+       struct tvp5150 *decoder = to_tvp5150(sd);
+       v4l2_std_id std;
+
+       if (f == NULL)
+               return -EINVAL;
+
+       tvp5150_reset(sd, 0);
+
+       /* Calculate height and width based on current standard */
+       if (decoder->norm == V4L2_STD_ALL)
+               std = tvp5150_read_std(sd);
+       else
+               std = decoder->norm;
+
+       f->width = 720;
+       if (std & V4L2_STD_525_60)
+               f->height = 480;
+       else
+               f->height = 576;
+
+       f->code = V4L2_MBUS_FMT_YUYV8_2X8;
+       f->field = V4L2_FIELD_SEQ_TB;
+       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width,
+                       f->height);
+       return 0;
+}
+
 /****************************************************************************
                        I2C Command
  ****************************************************************************/
@@ -931,6 +995,9 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
 
 static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
        .s_routing = tvp5150_s_routing,
+       .enum_mbus_fmt = tvp5150_enum_mbus_fmt,
+       .s_mbus_fmt = tvp5150_mbus_fmt,
+       .try_mbus_fmt = tvp5150_mbus_fmt,
 };
 
 static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
index d7f97513b2894c61902ed9783898997acae0893a..89fec029e9246c6933b7cfa6aea9441fc403536b 100644 (file)
@@ -110,42 +110,20 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap,
 
        unsigned char addr;
        int ret;
-       if ((flags & I2C_M_TEN)) {
-               /* a ten bit address */
-               addr = 0xf0 | ((msg->addr >> 7) & 0x03);
-               /* try extended address code... */
-               ret = try_write_address(i2c_adap, addr, retries);
-               if (ret != 1) {
-                       dev_err(&i2c_adap->dev,
-                               "died at extended address code, while writing\n");
-                       return -EREMOTEIO;
-               }
-               add[0] = addr;
-               if (flags & I2C_M_RD) {
-                       /* okay, now switch into reading mode */
-                       addr |= 0x01;
-                       ret = try_read_address(i2c_adap, addr, retries);
-                       if (ret != 1) {
-                               dev_err(&i2c_adap->dev,
-                                       "died at extended address code, while reading\n");
-                               return -EREMOTEIO;
-                       }
-               }
 
-       } else {                /* normal 7bit address  */
-               addr = (msg->addr << 1);
-               if (flags & I2C_M_RD)
-                       addr |= 1;
+       addr = (msg->addr << 1);
+       if (flags & I2C_M_RD)
+               addr |= 1;
 
-               add[0] = addr;
-               if (flags & I2C_M_RD)
-                       ret = try_read_address(i2c_adap, addr, retries);
-               else
-                       ret = try_write_address(i2c_adap, addr, retries);
+       add[0] = addr;
+       if (flags & I2C_M_RD)
+               ret = try_read_address(i2c_adap, addr, retries);
+       else
+               ret = try_write_address(i2c_adap, addr, retries);
+
+       if (ret != 1)
+               return -EREMOTEIO;
 
-               if (ret != 1)
-                       return -EREMOTEIO;
-       }
        return 0;
 }
 
@@ -184,7 +162,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
 
 static u32 functionality(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 /* -----exported algorithm data: ------------------------------------- */
index 2956a7637219acd6735a53f7d5292fec4ad45926..6c197da531b239b7dcc9c38058842c1b9af93c1c 100644 (file)
@@ -1,5 +1,6 @@
 config USB_VIDEO_CLASS
        tristate "USB Video Class (UVC)"
+       select VIDEOBUF2_VMALLOC
        ---help---
          Support for the USB Video Class (UVC).  Currently only video
          input devices, such as webcams, are supported.
index 2071ca8a2f031d86bb876fde6e3dcd79af31b92a..c26d12fdb8f4ef12d67222c40d99675cc0a045c5 100644 (file)
@@ -1,5 +1,5 @@
 uvcvideo-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
-                 uvc_status.o uvc_isight.o
+                 uvc_status.o uvc_isight.o uvc_debugfs.o
 ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
 uvcvideo-objs  += uvc_entity.o
 endif
index 254d32688843bdc3f0a38a782e13fef2ec8d5a18..0efd3b10b3537f94662bfb8be82f87ad5f3aee18 100644 (file)
@@ -878,8 +878,21 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
                                     chain->dev->intfnum, ctrl->info.selector,
                                     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
                                     ctrl->info.size);
-               if (ret < 0)
-                       return ret;
+               if (ret < 0) {
+                       if (UVC_ENTITY_TYPE(ctrl->entity) !=
+                           UVC_VC_EXTENSION_UNIT)
+                               return ret;
+
+                       /* GET_RES is mandatory for XU controls, but some
+                        * cameras still choke on it. Ignore errors and set the
+                        * resolution value to zero.
+                        */
+                       uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
+                                     "UVC non compliance - GET_RES failed on "
+                                     "an XU control. Enabling workaround.\n");
+                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
+                              ctrl->info.size);
+               }
        }
 
        ctrl->cached = 1;
@@ -1861,7 +1874,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
                if (ncontrols == 0)
                        continue;
 
-               entity->controls = kzalloc(ncontrols * sizeof(*ctrl),
+               entity->controls = kcalloc(ncontrols, sizeof(*ctrl),
                                           GFP_KERNEL);
                if (entity->controls == NULL)
                        return -ENOMEM;
diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/video/uvc/uvc_debugfs.c
new file mode 100644 (file)
index 0000000..14561a5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *      uvc_debugfs.c --  USB Video Class driver - Debugging support
+ *
+ *      Copyright (C) 2011
+ *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "uvcvideo.h"
+
+/* -----------------------------------------------------------------------------
+ * Statistics
+ */
+
+#define UVC_DEBUGFS_BUF_SIZE   1024
+
+struct uvc_debugfs_buffer {
+       size_t count;
+       char data[UVC_DEBUGFS_BUF_SIZE];
+};
+
+static int uvc_debugfs_stats_open(struct inode *inode, struct file *file)
+{
+       struct uvc_streaming *stream = inode->i_private;
+       struct uvc_debugfs_buffer *buf;
+
+       buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data));
+
+       file->private_data = buf;
+       return 0;
+}
+
+static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf,
+                                     size_t nbytes, loff_t *ppos)
+{
+       struct uvc_debugfs_buffer *buf = file->private_data;
+
+       return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
+                                      buf->count);
+}
+
+static int uvc_debugfs_stats_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       file->private_data = NULL;
+
+       return 0;
+}
+
+static const struct file_operations uvc_debugfs_stats_fops = {
+       .owner = THIS_MODULE,
+       .open = uvc_debugfs_stats_open,
+       .llseek = no_llseek,
+       .read = uvc_debugfs_stats_read,
+       .release = uvc_debugfs_stats_release,
+};
+
+/* -----------------------------------------------------------------------------
+ * Global and stream initialization/cleanup
+ */
+
+static struct dentry *uvc_debugfs_root_dir;
+
+int uvc_debugfs_init_stream(struct uvc_streaming *stream)
+{
+       struct usb_device *udev = stream->dev->udev;
+       struct dentry *dent;
+       char dir_name[32];
+
+       if (uvc_debugfs_root_dir == NULL)
+               return -ENODEV;
+
+       sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum);
+
+       dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir);
+       if (IS_ERR_OR_NULL(dent)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs %s "
+                          "directory.\n", dir_name);
+               return -ENODEV;
+       }
+
+       stream->debugfs_dir = dent;
+
+       dent = debugfs_create_file("stats", 0444, stream->debugfs_dir,
+                                  stream, &uvc_debugfs_stats_fops);
+       if (IS_ERR_OR_NULL(dent)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n");
+               uvc_debugfs_cleanup_stream(stream);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
+{
+       if (stream->debugfs_dir == NULL)
+               return;
+
+       debugfs_remove_recursive(stream->debugfs_dir);
+       stream->debugfs_dir = NULL;
+}
+
+int uvc_debugfs_init(void)
+{
+       struct dentry *dir;
+
+       dir = debugfs_create_dir("uvcvideo", usb_debug_root);
+       if (IS_ERR_OR_NULL(dir)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
+               return -ENODATA;
+       }
+
+       uvc_debugfs_root_dir = dir;
+       return 0;
+}
+
+void uvc_debugfs_cleanup(void)
+{
+       if (uvc_debugfs_root_dir != NULL)
+               debugfs_remove_recursive(uvc_debugfs_root_dir);
+}
index 656d4c9e3b9f85a07d96a57b5401b13e9526aa4d..a240d43d15d1b595720ff31925182d17b41b982e 100644 (file)
@@ -1675,6 +1675,8 @@ static void uvc_unregister_video(struct uvc_device *dev)
 
                video_unregister_device(stream->vdev);
                stream->vdev = NULL;
+
+               uvc_debugfs_cleanup_stream(stream);
        }
 
        /* Decrement the stream count and call uvc_delete explicitly if there
@@ -1700,6 +1702,8 @@ static int uvc_register_video(struct uvc_device *dev,
                return ret;
        }
 
+       uvc_debugfs_init_stream(stream);
+
        /* Register the device with V4L. */
        vdev = video_device_alloc();
        if (vdev == NULL) {
@@ -2033,6 +2037,15 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
  * though they are compliant.
  */
 static struct usb_device_id uvc_ids[] = {
+       /* LogiLink Wireless Webcam */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0416,
+         .idProduct            = 0xa91a,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
        /* Genius eFace 2025 */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2396,17 +2409,24 @@ struct uvc_driver uvc_driver = {
 
 static int __init uvc_init(void)
 {
-       int result;
+       int ret;
+
+       uvc_debugfs_init();
 
-       result = usb_register(&uvc_driver.driver);
-       if (result == 0)
-               printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
-       return result;
+       ret = usb_register(&uvc_driver.driver);
+       if (ret < 0) {
+               uvc_debugfs_cleanup();
+               return ret;
+       }
+
+       printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
+       return 0;
 }
 
 static void __exit uvc_cleanup(void)
 {
        usb_deregister(&uvc_driver.driver);
+       uvc_debugfs_cleanup();
 }
 
 module_init(uvc_init);
index 74bbe8f18f3e51a6b337a22963a8de2474809763..8510e7259e7639cdf30e343801fa38792dd619f0 100644 (file)
@@ -74,7 +74,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
         * Empty buffers (bytesused == 0) don't trigger end of frame detection
         * as it doesn't make sense to return an empty buffer.
         */
-       if (is_header && buf->buf.bytesused != 0) {
+       if (is_header && buf->bytesused != 0) {
                buf->state = UVC_BUF_STATE_DONE;
                return -EAGAIN;
        }
@@ -83,13 +83,13 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
         * contain no data.
         */
        if (!is_header) {
-               maxlen = buf->buf.length - buf->buf.bytesused;
-               mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+               maxlen = buf->length - buf->bytesused;
+               mem = buf->mem + buf->bytesused;
                nbytes = min(len, maxlen);
                memcpy(mem, data, nbytes);
-               buf->buf.bytesused += nbytes;
+               buf->bytesused += nbytes;
 
-               if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
+               if (len > maxlen || buf->bytesused == buf->length) {
                        uvc_trace(UVC_TRACE_FRAME, "Frame complete "
                                  "(overflow).\n");
                        buf->state = UVC_BUF_STATE_DONE;
index 677691c44500f1ee0d8212c6639acf64861d1428..518f77d3a4d820bad41129be9ab623077ada54dc 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/list.h>
@@ -19,7 +20,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <linux/atomic.h>
+#include <media/videobuf2-vmalloc.h>
 
 #include "uvcvideo.h"
 
  * Video queues is initialized by uvc_queue_init(). The function performs
  * basic initialization of the uvc_video_queue struct and never fails.
  *
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- *    The buffers are added to the main and irq queues. Both operations are
- *    protected by the queue lock, and the later is protected by the irq
- *    spinlock as well.
- *
- *    The completion handler fetches a buffer from the irq queue and fills it
- *    with video data. If no buffer is available (irq queue empty), the handler
- *    returns immediately.
- *
- *    When the buffer is full, the completion handler removes it from the irq
- *    queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue.
- *    At that point, any process waiting on the buffer will be woken up. If a
- *    process tries to dequeue a buffer after it has been marked done, the
- *    dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- *    disconnected.
- *
- *    When the device is disconnected, the kernel calls the completion handler
- *    with an appropriate status code. The handler marks all buffers in the
- *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- *    that any process waiting on a buffer gets woken up.
- *
- *    Waking up up the first buffer on the irq list is not enough, as the
- *    process waiting on the buffer might restart the dequeue operation
- *    immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
  */
 
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
-                   int drop_corrupted)
-{
-       mutex_init(&queue->mutex);
-       spin_lock_init(&queue->irqlock);
-       INIT_LIST_HEAD(&queue->mainqueue);
-       INIT_LIST_HEAD(&queue->irqqueue);
-       queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
-       queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
  */
-static int __uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
 {
-       unsigned int i;
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+       struct uvc_streaming *stream =
+                       container_of(queue, struct uvc_streaming, queue);
 
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
+       if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+               *nbuffers = UVC_MAX_VIDEO_BUFFERS;
 
-       if (queue->count) {
-               uvc_queue_cancel(queue, 0);
-               INIT_LIST_HEAD(&queue->mainqueue);
-               vfree(queue->mem);
-               queue->count = 0;
-       }
+       *nplanes = 1;
+
+       sizes[0] = stream->ctrl.dwMaxVideoFrameSize;
 
        return 0;
 }
 
-int uvc_free_buffers(struct uvc_video_queue *queue)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
-       int ret;
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
-       mutex_lock(&queue->mutex);
-       ret = __uvc_free_buffers(queue);
-       mutex_unlock(&queue->mutex);
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+               return -EINVAL;
+       }
 
-       return ret;
-}
+       if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+               return -ENODEV;
 
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
-               unsigned int buflength)
-{
-       unsigned int bufsize = PAGE_ALIGN(buflength);
-       unsigned int i;
-       void *mem = NULL;
-       int ret;
+       buf->state = UVC_BUF_STATE_QUEUED;
+       buf->error = 0;
+       buf->mem = vb2_plane_vaddr(vb, 0);
+       buf->length = vb2_plane_size(vb, 0);
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               buf->bytesused = 0;
+       else
+               buf->bytesused = vb2_get_plane_payload(vb, 0);
 
-       if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
-               nbuffers = UVC_MAX_VIDEO_BUFFERS;
+       return 0;
+}
 
-       mutex_lock(&queue->mutex);
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+       unsigned long flags;
 
-       if ((ret = __uvc_free_buffers(queue)) < 0)
-               goto done;
+       spin_lock_irqsave(&queue->irqlock, flags);
+       if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+               list_add_tail(&buf->queue, &queue->irqqueue);
+       } else {
+               /* If the device is disconnected return the buffer to userspace
+                * directly. The next QBUF call will fail with -ENODEV.
+                */
+               buf->state = UVC_BUF_STATE_ERROR;
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+       }
 
-       /* Bail out if no buffers should be allocated. */
-       if (nbuffers == 0)
-               goto done;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+}
 
-       /* Decrement the number of buffers until allocation succeeds. */
-       for (; nbuffers > 0; --nbuffers) {
-               mem = vmalloc_32(nbuffers * bufsize);
-               if (mem != NULL)
-                       break;
-       }
+static int uvc_buffer_finish(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_streaming *stream =
+                       container_of(queue, struct uvc_streaming, queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
-       if (mem == NULL) {
-               ret = -ENOMEM;
-               goto done;
-       }
+       uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+       return 0;
+}
 
-       for (i = 0; i < nbuffers; ++i) {
-               memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
-               queue->buffer[i].buf.index = i;
-               queue->buffer[i].buf.m.offset = i * bufsize;
-               queue->buffer[i].buf.length = buflength;
-               queue->buffer[i].buf.type = queue->type;
-               queue->buffer[i].buf.field = V4L2_FIELD_NONE;
-               queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
-               queue->buffer[i].buf.flags = 0;
-               init_waitqueue_head(&queue->buffer[i].wait);
-       }
+static struct vb2_ops uvc_queue_qops = {
+       .queue_setup = uvc_queue_setup,
+       .buf_prepare = uvc_buffer_prepare,
+       .buf_queue = uvc_buffer_queue,
+       .buf_finish = uvc_buffer_finish,
+};
 
-       queue->mem = mem;
-       queue->count = nbuffers;
-       queue->buf_size = bufsize;
-       ret = nbuffers;
+void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+                   int drop_corrupted)
+{
+       queue->queue.type = type;
+       queue->queue.io_modes = VB2_MMAP;
+       queue->queue.drv_priv = queue;
+       queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+       queue->queue.ops = &uvc_queue_qops;
+       queue->queue.mem_ops = &vb2_vmalloc_memops;
+       vb2_queue_init(&queue->queue);
 
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       mutex_init(&queue->mutex);
+       spin_lock_init(&queue->irqlock);
+       INIT_LIST_HEAD(&queue->irqqueue);
+       queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
 }
 
-/*
- * Check if buffers have been allocated.
+/* -----------------------------------------------------------------------------
+ * V4L2 queue operations
  */
-int uvc_queue_allocated(struct uvc_video_queue *queue)
+
+int uvc_alloc_buffers(struct uvc_video_queue *queue,
+                     struct v4l2_requestbuffers *rb)
 {
-       int allocated;
+       int ret;
 
        mutex_lock(&queue->mutex);
-       allocated = queue->count != 0;
+       ret = vb2_reqbufs(&queue->queue, rb);
        mutex_unlock(&queue->mutex);
 
-       return allocated;
+       return ret ? ret : rb->count;
 }
 
-static void __uvc_query_buffer(struct uvc_buffer *buf,
-               struct v4l2_buffer *v4l2_buf)
+void uvc_free_buffers(struct uvc_video_queue *queue)
 {
-       memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
-       if (buf->vma_use_count)
-               v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       switch (buf->state) {
-       case UVC_BUF_STATE_ERROR:
-       case UVC_BUF_STATE_DONE:
-               v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
-               break;
-       case UVC_BUF_STATE_QUEUED:
-       case UVC_BUF_STATE_ACTIVE:
-       case UVC_BUF_STATE_READY:
-               v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               break;
-       case UVC_BUF_STATE_IDLE:
-       default:
-               break;
-       }
+       mutex_lock(&queue->mutex);
+       vb2_queue_release(&queue->queue);
+       mutex_unlock(&queue->mutex);
 }
 
-int uvc_query_buffer(struct uvc_video_queue *queue,
-               struct v4l2_buffer *v4l2_buf)
+int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
 {
-       int ret = 0;
+       int ret;
 
        mutex_lock(&queue->mutex);
-       if (v4l2_buf->index >= queue->count) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
-
-done:
+       ret = vb2_querybuf(&queue->queue, buf);
        mutex_unlock(&queue->mutex);
+
        return ret;
 }
 
-/*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
- */
-int uvc_queue_buffer(struct uvc_video_queue *queue,
-       struct v4l2_buffer *v4l2_buf)
+int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
 {
-       struct uvc_buffer *buf;
-       unsigned long flags;
-       int ret = 0;
-
-       uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
-
-       if (v4l2_buf->type != queue->type ||
-           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-                       "and/or memory (%u).\n", v4l2_buf->type,
-                       v4l2_buf->memory);
-               return -EINVAL;
-       }
+       int ret;
 
        mutex_lock(&queue->mutex);
-       if (v4l2_buf->index >= queue->count) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       buf = &queue->buffer[v4l2_buf->index];
-       if (buf->state != UVC_BUF_STATE_IDLE) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
-                       "(%u).\n", buf->state);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           v4l2_buf->bytesused > buf->buf.length) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       spin_lock_irqsave(&queue->irqlock, flags);
-       if (queue->flags & UVC_QUEUE_DISCONNECTED) {
-               spin_unlock_irqrestore(&queue->irqlock, flags);
-               ret = -ENODEV;
-               goto done;
-       }
-       buf->state = UVC_BUF_STATE_QUEUED;
-       if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               buf->buf.bytesused = 0;
-       else
-               buf->buf.bytesused = v4l2_buf->bytesused;
-
-       list_add_tail(&buf->stream, &queue->mainqueue);
-       list_add_tail(&buf->queue, &queue->irqqueue);
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
+       ret = vb2_qbuf(&queue->queue, buf);
        mutex_unlock(&queue->mutex);
-       return ret;
-}
 
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
-       if (nonblocking) {
-               return (buf->state != UVC_BUF_STATE_QUEUED &&
-                       buf->state != UVC_BUF_STATE_ACTIVE &&
-                       buf->state != UVC_BUF_STATE_READY)
-                       ? 0 : -EAGAIN;
-       }
-
-       return wait_event_interruptible(buf->wait,
-               buf->state != UVC_BUF_STATE_QUEUED &&
-               buf->state != UVC_BUF_STATE_ACTIVE &&
-               buf->state != UVC_BUF_STATE_READY);
+       return ret;
 }
 
-/*
- * Dequeue a video buffer. If nonblocking is false, block until a buffer is
- * available.
- */
-int uvc_dequeue_buffer(struct uvc_video_queue *queue,
-               struct v4l2_buffer *v4l2_buf, int nonblocking)
+int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
+                      int nonblocking)
 {
-       struct uvc_buffer *buf;
-       int ret = 0;
-
-       if (v4l2_buf->type != queue->type ||
-           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-                       "and/or memory (%u).\n", v4l2_buf->type,
-                       v4l2_buf->memory);
-               return -EINVAL;
-       }
+       int ret;
 
        mutex_lock(&queue->mutex);
-       if (list_empty(&queue->mainqueue)) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-       if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
-               goto done;
-
-       uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
-               buf->buf.index, buf->state, buf->buf.bytesused);
-
-       switch (buf->state) {
-       case UVC_BUF_STATE_ERROR:
-               uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
-                       "(transmission error).\n");
-               ret = -EIO;
-       case UVC_BUF_STATE_DONE:
-               buf->state = UVC_BUF_STATE_IDLE;
-               break;
-
-       case UVC_BUF_STATE_IDLE:
-       case UVC_BUF_STATE_QUEUED:
-       case UVC_BUF_STATE_ACTIVE:
-       case UVC_BUF_STATE_READY:
-       default:
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
-                       "(driver bug?).\n", buf->state);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       list_del(&buf->stream);
-       __uvc_query_buffer(buf, v4l2_buf);
-
-done:
+       ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
        mutex_unlock(&queue->mutex);
-       return ret;
-}
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
+       return ret;
 }
 
-static const struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
-
-/*
- * Memory-map a video buffer.
- *
- * This function implements video buffers memory mapping and is intended to be
- * used by the device mmap handler.
- */
 int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 {
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
-
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
+       int ret;
 
        mutex_lock(&queue->mutex);
+       ret = vb2_mmap(&queue->queue, vma);
+       mutex_unlock(&queue->mutex);
 
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-#ifdef CONFIG_MMU
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-#endif
+       return ret;
+}
 
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
+unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
+                           poll_table *wait)
+{
+       unsigned int ret;
 
-done:
+       mutex_lock(&queue->mutex);
+       ret = vb2_poll(&queue->queue, file, wait);
        mutex_unlock(&queue->mutex);
+
        return ret;
 }
 
-/*
- * Poll the video queue.
+/* -----------------------------------------------------------------------------
  *
- * This function implements video queue polling and is intended to be used by
- * the device poll handler.
  */
-unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
-               poll_table *wait)
+
+/*
+ * Check if buffers have been allocated.
+ */
+int uvc_queue_allocated(struct uvc_video_queue *queue)
 {
-       struct uvc_buffer *buf;
-       unsigned int mask = 0;
+       int allocated;
 
        mutex_lock(&queue->mutex);
-       if (list_empty(&queue->mainqueue)) {
-               mask |= POLLERR;
-               goto done;
-       }
-       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
-       poll_wait(file, &buf->wait, wait);
-       if (buf->state == UVC_BUF_STATE_DONE ||
-           buf->state == UVC_BUF_STATE_ERROR) {
-               if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       mask |= POLLIN | POLLRDNORM;
-               else
-                       mask |= POLLOUT | POLLWRNORM;
-       }
-
-done:
+       allocated = vb2_is_busy(&queue->queue);
        mutex_unlock(&queue->mutex);
-       return mask;
+
+       return allocated;
 }
 
 #ifndef CONFIG_MMU
@@ -515,7 +260,7 @@ unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
                ret = -EINVAL;
                goto done;
        }
-       ret = (unsigned long)queue->mem + buffer->buf.m.offset;
+       ret = (unsigned long)buf->mem;
 done:
        mutex_unlock(&queue->mutex);
        return ret;
@@ -540,27 +285,24 @@ done:
  */
 int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 {
-       unsigned int i;
-       int ret = 0;
+       unsigned long flags;
+       int ret;
 
        mutex_lock(&queue->mutex);
        if (enable) {
-               if (uvc_queue_streaming(queue)) {
-                       ret = -EBUSY;
+               ret = vb2_streamon(&queue->queue, queue->queue.type);
+               if (ret < 0)
                        goto done;
-               }
-               queue->flags |= UVC_QUEUE_STREAMING;
+
                queue->buf_used = 0;
        } else {
-               uvc_queue_cancel(queue, 0);
-               INIT_LIST_HEAD(&queue->mainqueue);
-
-               for (i = 0; i < queue->count; ++i) {
-                       queue->buffer[i].error = 0;
-                       queue->buffer[i].state = UVC_BUF_STATE_IDLE;
-               }
+               ret = vb2_streamoff(&queue->queue, queue->queue.type);
+               if (ret < 0)
+                       goto done;
 
-               queue->flags &= ~UVC_QUEUE_STREAMING;
+               spin_lock_irqsave(&queue->irqlock, flags);
+               INIT_LIST_HEAD(&queue->irqqueue);
+               spin_unlock_irqrestore(&queue->irqlock, flags);
        }
 
 done:
@@ -591,12 +333,12 @@ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
                                       queue);
                list_del(&buf->queue);
                buf->state = UVC_BUF_STATE_ERROR;
-               wake_up(&buf->wait);
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
        }
        /* This must be protected by the irqlock spinlock to avoid race
-        * conditions between uvc_queue_buffer and the disconnection event that
+        * conditions between uvc_buffer_queue and the disconnection event that
         * could result in an interruptible wait in uvc_dequeue_buffer. Do not
-        * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
+        * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED
         * state outside the queue code.
         */
        if (disconnect)
@@ -613,14 +355,12 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
        if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
                buf->error = 0;
                buf->state = UVC_BUF_STATE_QUEUED;
-               buf->buf.bytesused = 0;
+               vb2_set_plane_payload(&buf->buf, 0, 0);
                return buf;
        }
 
        spin_lock_irqsave(&queue->irqlock, flags);
        list_del(&buf->queue);
-       buf->error = 0;
-       buf->state = UVC_BUF_STATE_DONE;
        if (!list_empty(&queue->irqqueue))
                nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
                                           queue);
@@ -628,7 +368,9 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
                nextbuf = NULL;
        spin_unlock_irqrestore(&queue->irqlock, flags);
 
-       wake_up(&buf->wait);
+       buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
+       vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+       vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+
        return nextbuf;
 }
-
index dadf11f704dc742e8fe21d8df0880f35e3b9128e..2ae4f880ea05ed5bd67bee2a4816fcea7ed464ae 100644 (file)
@@ -58,6 +58,15 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
                break;
 
        case V4L2_CTRL_TYPE_MENU:
+               /* Prevent excessive memory consumption, as well as integer
+                * overflows.
+                */
+               if (xmap->menu_count == 0 ||
+                   xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+
                size = xmap->menu_count * sizeof(*map->menu_info);
                map->menu_info = kmalloc(size, GFP_KERNEL);
                if (map->menu_info == NULL) {
@@ -513,10 +522,7 @@ static int uvc_v4l2_release(struct file *file)
        /* Only free resources if this is a privileged handle. */
        if (uvc_has_privileges(handle)) {
                uvc_video_enable(stream, 0);
-
-               if (uvc_free_buffers(&stream->queue) < 0)
-                       uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
-                                       "free buffers.\n");
+               uvc_free_buffers(&stream->queue);
        }
 
        /* Release the file handle. */
@@ -914,19 +920,11 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
        /* Buffers & streaming */
        case VIDIOC_REQBUFS:
-       {
-               struct v4l2_requestbuffers *rb = arg;
-
-               if (rb->type != stream->type ||
-                   rb->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
-
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
                mutex_lock(&stream->mutex);
-               ret = uvc_alloc_buffers(&stream->queue, rb->count,
-                                       stream->ctrl.dwMaxVideoFrameSize);
+               ret = uvc_alloc_buffers(&stream->queue, arg);
                mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
@@ -934,18 +932,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (ret == 0)
                        uvc_dismiss_privileges(handle);
 
-               rb->count = ret;
                ret = 0;
                break;
-       }
 
        case VIDIOC_QUERYBUF:
        {
                struct v4l2_buffer *buf = arg;
 
-               if (buf->type != stream->type)
-                       return -EINVAL;
-
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
index b015e8e5e8b08ad6ade229a02e63f2ea2396edaf..c7e69b8f81c9555b5a1296b96355957b8e91089b 100644 (file)
@@ -351,25 +351,553 @@ done:
        return ret;
 }
 
-int uvc_commit_video(struct uvc_streaming *stream,
-       struct uvc_streaming_control *probe)
+static int uvc_commit_video(struct uvc_streaming *stream,
+                           struct uvc_streaming_control *probe)
 {
        return uvc_set_video_ctrl(stream, probe, 0);
 }
 
+/* -----------------------------------------------------------------------------
+ * Clocks and timestamps
+ */
+
+static void
+uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+                      const __u8 *data, int len)
+{
+       struct uvc_clock_sample *sample;
+       unsigned int header_size;
+       bool has_pts = false;
+       bool has_scr = false;
+       unsigned long flags;
+       struct timespec ts;
+       u16 host_sof;
+       u16 dev_sof;
+
+       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+       case UVC_STREAM_PTS | UVC_STREAM_SCR:
+               header_size = 12;
+               has_pts = true;
+               has_scr = true;
+               break;
+       case UVC_STREAM_PTS:
+               header_size = 6;
+               has_pts = true;
+               break;
+       case UVC_STREAM_SCR:
+               header_size = 8;
+               has_scr = true;
+               break;
+       default:
+               header_size = 2;
+               break;
+       }
+
+       /* Check for invalid headers. */
+       if (len < header_size)
+               return;
+
+       /* Extract the timestamps:
+        *
+        * - store the frame PTS in the buffer structure
+        * - if the SCR field is present, retrieve the host SOF counter and
+        *   kernel timestamps and store them with the SCR STC and SOF fields
+        *   in the ring buffer
+        */
+       if (has_pts && buf != NULL)
+               buf->pts = get_unaligned_le32(&data[2]);
+
+       if (!has_scr)
+               return;
+
+       /* To limit the amount of data, drop SCRs with an SOF identical to the
+        * previous one.
+        */
+       dev_sof = get_unaligned_le16(&data[header_size - 2]);
+       if (dev_sof == stream->clock.last_sof)
+               return;
+
+       stream->clock.last_sof = dev_sof;
+
+       host_sof = usb_get_current_frame_number(stream->dev->udev);
+       ktime_get_ts(&ts);
+
+       /* The UVC specification allows device implementations that can't obtain
+        * the USB frame number to keep their own frame counters as long as they
+        * match the size and frequency of the frame number associated with USB
+        * SOF tokens. The SOF values sent by such devices differ from the USB
+        * SOF tokens by a fixed offset that needs to be estimated and accounted
+        * for to make timestamp recovery as accurate as possible.
+        *
+        * The offset is estimated the first time a device SOF value is received
+        * as the difference between the host and device SOF values. As the two
+        * SOF values can differ slightly due to transmission delays, consider
+        * that the offset is null if the difference is not higher than 10 ms
+        * (negative differences can not happen and are thus considered as an
+        * offset). The video commit control wDelay field should be used to
+        * compute a dynamic threshold instead of using a fixed 10 ms value, but
+        * devices don't report reliable wDelay values.
+        *
+        * See uvc_video_clock_host_sof() for an explanation regarding why only
+        * the 8 LSBs of the delta are kept.
+        */
+       if (stream->clock.sof_offset == (u16)-1) {
+               u16 delta_sof = (host_sof - dev_sof) & 255;
+               if (delta_sof >= 10)
+                       stream->clock.sof_offset = delta_sof;
+               else
+                       stream->clock.sof_offset = 0;
+       }
+
+       dev_sof = (dev_sof + stream->clock.sof_offset) & 2047;
+
+       spin_lock_irqsave(&stream->clock.lock, flags);
+
+       sample = &stream->clock.samples[stream->clock.head];
+       sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
+       sample->dev_sof = dev_sof;
+       sample->host_sof = host_sof;
+       sample->host_ts = ts;
+
+       /* Update the sliding window head and count. */
+       stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
+
+       if (stream->clock.count < stream->clock.size)
+               stream->clock.count++;
+
+       spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
+static int uvc_video_clock_init(struct uvc_streaming *stream)
+{
+       struct uvc_clock *clock = &stream->clock;
+
+       spin_lock_init(&clock->lock);
+       clock->head = 0;
+       clock->count = 0;
+       clock->size = 32;
+       clock->last_sof = -1;
+       clock->sof_offset = -1;
+
+       clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
+                                GFP_KERNEL);
+       if (clock->samples == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void uvc_video_clock_cleanup(struct uvc_streaming *stream)
+{
+       kfree(stream->clock.samples);
+       stream->clock.samples = NULL;
+}
+
+/*
+ * uvc_video_clock_host_sof - Return the host SOF value for a clock sample
+ *
+ * Host SOF counters reported by usb_get_current_frame_number() usually don't
+ * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame
+ * schedule window. They can be limited to 8, 9 or 10 bits depending on the host
+ * controller and its configuration.
+ *
+ * We thus need to recover the SOF value corresponding to the host frame number.
+ * As the device and host frame numbers are sampled in a short interval, the
+ * difference between their values should be equal to a small delta plus an
+ * integer multiple of 256 caused by the host frame number limited precision.
+ *
+ * To obtain the recovered host SOF value, compute the small delta by masking
+ * the high bits of the host frame counter and device SOF difference and add it
+ * to the device SOF value.
+ */
+static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
+{
+       /* The delta value can be negative. */
+       s8 delta_sof;
+
+       delta_sof = (sample->host_sof - sample->dev_sof) & 255;
+
+       return (sample->dev_sof + delta_sof) & 2047;
+}
+
+/*
+ * uvc_video_clock_update - Update the buffer timestamp
+ *
+ * This function converts the buffer PTS timestamp to the host clock domain by
+ * going through the USB SOF clock domain and stores the result in the V4L2
+ * buffer timestamp field.
+ *
+ * The relationship between the device clock and the host clock isn't known.
+ * However, the device and the host share the common USB SOF clock which can be
+ * used to recover that relationship.
+ *
+ * The relationship between the device clock and the USB SOF clock is considered
+ * to be linear over the clock samples sliding window and is given by
+ *
+ * SOF = m * PTS + p
+ *
+ * Several methods to compute the slope (m) and intercept (p) can be used. As
+ * the clock drift should be small compared to the sliding window size, we
+ * assume that the line that goes through the points at both ends of the window
+ * is a good approximation. Naming those points P1 and P2, we get
+ *
+ * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS
+ *     + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)
+ *
+ * or
+ *
+ * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
+ *
+ * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * computed with
+ *
+ * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
+ *
+ * SOF values are coded on 11 bits by USB. We extend their precision with 16
+ * decimal bits, leading to a 11.16 coding.
+ *
+ * TODO: To avoid surprises with device clock values, PTS/STC timestamps should
+ * be normalized using the nominal device clock frequency reported through the
+ * UVC descriptors.
+ *
+ * Both the PTS/STC and SOF counters roll over, after a fixed but device
+ * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the
+ * sliding window size is smaller than the rollover period, differences computed
+ * on unsigned integers will produce the correct result. However, the p term in
+ * the linear relations will be miscomputed.
+ *
+ * To fix the issue, we subtract a constant from the PTS and STC values to bring
+ * PTS to half the 32 bit STC range. The sliding window STC values then fit into
+ * the 32 bit range without any rollover.
+ *
+ * Similarly, we add 2048 to the device SOF values to make sure that the SOF
+ * computed by (1) will never be smaller than 0. This offset is then compensated
+ * by adding 2048 to the SOF values used in (2). However, this doesn't prevent
+ * rollovers between (1) and (2): the SOF value computed by (1) can be slightly
+ * lower than 4096, and the host SOF counters can have rolled over to 2048. This
+ * case is handled by subtracting 2048 from the SOF value if it exceeds the host
+ * SOF value at the end of the sliding window.
+ *
+ * Finally we subtract a constant from the host timestamps to bring the first
+ * timestamp of the sliding window to 1s.
+ */
+void uvc_video_clock_update(struct uvc_streaming *stream,
+                           struct v4l2_buffer *v4l2_buf,
+                           struct uvc_buffer *buf)
+{
+       struct uvc_clock *clock = &stream->clock;
+       struct uvc_clock_sample *first;
+       struct uvc_clock_sample *last;
+       unsigned long flags;
+       struct timespec ts;
+       u32 delta_stc;
+       u32 y1, y2;
+       u32 x1, x2;
+       u32 mean;
+       u32 sof;
+       u32 div;
+       u32 rem;
+       u64 y;
+
+       spin_lock_irqsave(&clock->lock, flags);
+
+       if (clock->count < clock->size)
+               goto done;
+
+       first = &clock->samples[clock->head];
+       last = &clock->samples[(clock->head - 1) % clock->size];
+
+       /* First step, PTS to SOF conversion. */
+       delta_stc = buf->pts - (1UL << 31);
+       x1 = first->dev_stc - delta_stc;
+       x2 = last->dev_stc - delta_stc;
+       y1 = (first->dev_sof + 2048) << 16;
+       y2 = (last->dev_sof + 2048) << 16;
+
+       if (y2 < y1)
+               y2 += 2048 << 16;
+
+       y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2
+         - (u64)y2 * (u64)x1;
+       y = div_u64(y, x2 - x1);
+
+       sof = y;
+
+       uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
+                 "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
+                 stream->dev->name, buf->pts,
+                 y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
+                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+                 x1, x2, y1, y2, clock->sof_offset);
+
+       /* Second step, SOF to host clock conversion. */
+       ts = timespec_sub(last->host_ts, first->host_ts);
+       x1 = (uvc_video_clock_host_sof(first) + 2048) << 16;
+       x2 = (uvc_video_clock_host_sof(last) + 2048) << 16;
+       y1 = NSEC_PER_SEC;
+       y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec;
+
+       if (x2 < x1)
+               x2 += 2048 << 16;
+
+       /* Interpolated and host SOF timestamps can wrap around at slightly
+        * different times. Handle this by adding or removing 2048 to or from
+        * the computed SOF value to keep it close to the SOF samples mean
+        * value.
+        */
+       mean = (x1 + x2) / 2;
+       if (mean - (1024 << 16) > sof)
+               sof += 2048 << 16;
+       else if (sof > mean + (1024 << 16))
+               sof -= 2048 << 16;
+
+       y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2
+         - (u64)y2 * (u64)x1;
+       y = div_u64(y, x2 - x1);
+
+       div = div_u64_rem(y, NSEC_PER_SEC, &rem);
+       ts.tv_sec = first->host_ts.tv_sec - 1 + div;
+       ts.tv_nsec = first->host_ts.tv_nsec + rem;
+       if (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_sec++;
+               ts.tv_nsec -= NSEC_PER_SEC;
+       }
+
+       uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
+                 "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+                 stream->dev->name,
+                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+                 y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
+                 v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec,
+                 x1, first->host_sof, first->dev_sof,
+                 x2, last->host_sof, last->dev_sof, y1, y2);
+
+       /* Update the V4L2 buffer. */
+       v4l2_buf->timestamp.tv_sec = ts.tv_sec;
+       v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+done:
+       spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
 /* ------------------------------------------------------------------------
- * Video codecs
+ * Stream statistics
  */
 
-/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
-#define UVC_STREAM_EOH (1 << 7)
-#define UVC_STREAM_ERR (1 << 6)
-#define UVC_STREAM_STI (1 << 5)
-#define UVC_STREAM_RES (1 << 4)
-#define UVC_STREAM_SCR (1 << 3)
-#define UVC_STREAM_PTS (1 << 2)
-#define UVC_STREAM_EOF (1 << 1)
-#define UVC_STREAM_FID (1 << 0)
+static void uvc_video_stats_decode(struct uvc_streaming *stream,
+               const __u8 *data, int len)
+{
+       unsigned int header_size;
+       bool has_pts = false;
+       bool has_scr = false;
+       u16 uninitialized_var(scr_sof);
+       u32 uninitialized_var(scr_stc);
+       u32 uninitialized_var(pts);
+
+       if (stream->stats.stream.nb_frames == 0 &&
+           stream->stats.frame.nb_packets == 0)
+               ktime_get_ts(&stream->stats.stream.start_ts);
+
+       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+       case UVC_STREAM_PTS | UVC_STREAM_SCR:
+               header_size = 12;
+               has_pts = true;
+               has_scr = true;
+               break;
+       case UVC_STREAM_PTS:
+               header_size = 6;
+               has_pts = true;
+               break;
+       case UVC_STREAM_SCR:
+               header_size = 8;
+               has_scr = true;
+               break;
+       default:
+               header_size = 2;
+               break;
+       }
+
+       /* Check for invalid headers. */
+       if (len < header_size || data[0] < header_size) {
+               stream->stats.frame.nb_invalid++;
+               return;
+       }
+
+       /* Extract the timestamps. */
+       if (has_pts)
+               pts = get_unaligned_le32(&data[2]);
+
+       if (has_scr) {
+               scr_stc = get_unaligned_le32(&data[header_size - 6]);
+               scr_sof = get_unaligned_le16(&data[header_size - 2]);
+       }
+
+       /* Is PTS constant through the whole frame ? */
+       if (has_pts && stream->stats.frame.nb_pts) {
+               if (stream->stats.frame.pts != pts) {
+                       stream->stats.frame.nb_pts_diffs++;
+                       stream->stats.frame.last_pts_diff =
+                               stream->stats.frame.nb_packets;
+               }
+       }
+
+       if (has_pts) {
+               stream->stats.frame.nb_pts++;
+               stream->stats.frame.pts = pts;
+       }
+
+       /* Do all frames have a PTS in their first non-empty packet, or before
+        * their first empty packet ?
+        */
+       if (stream->stats.frame.size == 0) {
+               if (len > header_size)
+                       stream->stats.frame.has_initial_pts = has_pts;
+               if (len == header_size && has_pts)
+                       stream->stats.frame.has_early_pts = true;
+       }
+
+       /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */
+       if (has_scr && stream->stats.frame.nb_scr) {
+               if (stream->stats.frame.scr_stc != scr_stc)
+                       stream->stats.frame.nb_scr_diffs++;
+       }
+
+       if (has_scr) {
+               /* Expand the SOF counter to 32 bits and store its value. */
+               if (stream->stats.stream.nb_frames > 0 ||
+                   stream->stats.frame.nb_scr > 0)
+                       stream->stats.stream.scr_sof_count +=
+                               (scr_sof - stream->stats.stream.scr_sof) % 2048;
+               stream->stats.stream.scr_sof = scr_sof;
+
+               stream->stats.frame.nb_scr++;
+               stream->stats.frame.scr_stc = scr_stc;
+               stream->stats.frame.scr_sof = scr_sof;
+
+               if (scr_sof < stream->stats.stream.min_sof)
+                       stream->stats.stream.min_sof = scr_sof;
+               if (scr_sof > stream->stats.stream.max_sof)
+                       stream->stats.stream.max_sof = scr_sof;
+       }
+
+       /* Record the first non-empty packet number. */
+       if (stream->stats.frame.size == 0 && len > header_size)
+               stream->stats.frame.first_data = stream->stats.frame.nb_packets;
+
+       /* Update the frame size. */
+       stream->stats.frame.size += len - header_size;
+
+       /* Update the packets counters. */
+       stream->stats.frame.nb_packets++;
+       if (len > header_size)
+               stream->stats.frame.nb_empty++;
+
+       if (data[1] & UVC_STREAM_ERR)
+               stream->stats.frame.nb_errors++;
+}
+
+static void uvc_video_stats_update(struct uvc_streaming *stream)
+{
+       struct uvc_stats_frame *frame = &stream->stats.frame;
+
+       uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, "
+                 "%u/%u/%u pts (%searly %sinitial), %u/%u scr, "
+                 "last pts/stc/sof %u/%u/%u\n",
+                 stream->sequence, frame->first_data,
+                 frame->nb_packets - frame->nb_empty, frame->nb_packets,
+                 frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts,
+                 frame->has_early_pts ? "" : "!",
+                 frame->has_initial_pts ? "" : "!",
+                 frame->nb_scr_diffs, frame->nb_scr,
+                 frame->pts, frame->scr_stc, frame->scr_sof);
+
+       stream->stats.stream.nb_frames++;
+       stream->stats.stream.nb_packets += stream->stats.frame.nb_packets;
+       stream->stats.stream.nb_empty += stream->stats.frame.nb_empty;
+       stream->stats.stream.nb_errors += stream->stats.frame.nb_errors;
+       stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid;
+
+       if (frame->has_early_pts)
+               stream->stats.stream.nb_pts_early++;
+       if (frame->has_initial_pts)
+               stream->stats.stream.nb_pts_initial++;
+       if (frame->last_pts_diff <= frame->first_data)
+               stream->stats.stream.nb_pts_constant++;
+       if (frame->nb_scr >= frame->nb_packets - frame->nb_empty)
+               stream->stats.stream.nb_scr_count_ok++;
+       if (frame->nb_scr_diffs + 1 == frame->nb_scr)
+               stream->stats.stream.nb_scr_diffs_ok++;
+
+       memset(&stream->stats.frame, 0, sizeof(stream->stats.frame));
+}
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+                           size_t size)
+{
+       unsigned int scr_sof_freq;
+       unsigned int duration;
+       struct timespec ts;
+       size_t count = 0;
+
+       ts.tv_sec = stream->stats.stream.stop_ts.tv_sec
+                 - stream->stats.stream.start_ts.tv_sec;
+       ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec
+                  - stream->stats.stream.start_ts.tv_nsec;
+       if (ts.tv_nsec < 0) {
+               ts.tv_sec--;
+               ts.tv_nsec += 1000000000;
+       }
+
+       /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF
+        * frequency this will not overflow before more than 1h.
+        */
+       duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+       if (duration != 0)
+               scr_sof_freq = stream->stats.stream.scr_sof_count * 1000
+                            / duration;
+       else
+               scr_sof_freq = 0;
+
+       count += scnprintf(buf + count, size - count,
+                          "frames:  %u\npackets: %u\nempty:   %u\n"
+                          "errors:  %u\ninvalid: %u\n",
+                          stream->stats.stream.nb_frames,
+                          stream->stats.stream.nb_packets,
+                          stream->stats.stream.nb_empty,
+                          stream->stats.stream.nb_errors,
+                          stream->stats.stream.nb_invalid);
+       count += scnprintf(buf + count, size - count,
+                          "pts: %u early, %u initial, %u ok\n",
+                          stream->stats.stream.nb_pts_early,
+                          stream->stats.stream.nb_pts_initial,
+                          stream->stats.stream.nb_pts_constant);
+       count += scnprintf(buf + count, size - count,
+                          "scr: %u count ok, %u diff ok\n",
+                          stream->stats.stream.nb_scr_count_ok,
+                          stream->stats.stream.nb_scr_diffs_ok);
+       count += scnprintf(buf + count, size - count,
+                          "sof: %u <= sof <= %u, freq %u.%03u kHz\n",
+                          stream->stats.stream.min_sof,
+                          stream->stats.stream.max_sof,
+                          scr_sof_freq / 1000, scr_sof_freq % 1000);
+
+       return count;
+}
+
+static void uvc_video_stats_start(struct uvc_streaming *stream)
+{
+       memset(&stream->stats, 0, sizeof(stream->stats));
+       stream->stats.stream.min_sof = 2048;
+}
+
+static void uvc_video_stats_stop(struct uvc_streaming *stream)
+{
+       ktime_get_ts(&stream->stats.stream.stop_ts);
+}
+
+/* ------------------------------------------------------------------------
+ * Video codecs
+ */
 
 /* Video payload decoding is handled by uvc_video_decode_start(),
  * uvc_video_decode_data() and uvc_video_decode_end().
@@ -416,14 +944,9 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
         * - bHeaderLength value must be at least 2 bytes (see above)
         * - bHeaderLength value can't be larger than the packet size.
         */
-       if (len < 2 || data[0] < 2 || data[0] > len)
+       if (len < 2 || data[0] < 2 || data[0] > len) {
+               stream->stats.frame.nb_invalid++;
                return -EINVAL;
-
-       /* Skip payloads marked with the error bit ("error frames"). */
-       if (data[1] & UVC_STREAM_ERR) {
-               uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit "
-                         "set).\n");
-               return -ENODATA;
        }
 
        fid = data[1] & UVC_STREAM_FID;
@@ -431,8 +954,14 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
        /* Increase the sequence number regardless of any buffer states, so
         * that discontinuous sequence numbers always indicate lost frames.
         */
-       if (stream->last_fid != fid)
+       if (stream->last_fid != fid) {
                stream->sequence++;
+               if (stream->sequence)
+                       uvc_video_stats_update(stream);
+       }
+
+       uvc_video_clock_decode(stream, buf, data, len);
+       uvc_video_stats_decode(stream, data, len);
 
        /* Store the payload FID bit and return immediately when the buffer is
         * NULL.
@@ -442,6 +971,13 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
                return -ENODATA;
        }
 
+       /* Mark the buffer as bad if the error bit is set. */
+       if (data[1] & UVC_STREAM_ERR) {
+               uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit "
+                         "set).\n");
+               buf->error = 1;
+       }
+
        /* Synchronize to the input stream by waiting for the FID bit to be
         * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
         * stream->last_fid is initialized to -1, so the first isochronous
@@ -467,9 +1003,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
                else
                        ktime_get_real_ts(&ts);
 
-               buf->buf.sequence = stream->sequence;
-               buf->buf.timestamp.tv_sec = ts.tv_sec;
-               buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+               buf->buf.v4l2_buf.sequence = stream->sequence;
+               buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
+               buf->buf.v4l2_buf.timestamp.tv_usec =
+                       ts.tv_nsec / NSEC_PER_USEC;
 
                /* TODO: Handle PTS and SCR. */
                buf->state = UVC_BUF_STATE_ACTIVE;
@@ -490,7 +1027,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
         * avoids detecting end of frame conditions at FID toggling if the
         * previous payload had the EOF bit set.
         */
-       if (fid != stream->last_fid && buf->buf.bytesused != 0) {
+       if (fid != stream->last_fid && buf->bytesused != 0) {
                uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
                                "toggled).\n");
                buf->state = UVC_BUF_STATE_READY;
@@ -505,7 +1042,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
 static void uvc_video_decode_data(struct uvc_streaming *stream,
                struct uvc_buffer *buf, const __u8 *data, int len)
 {
-       struct uvc_video_queue *queue = &stream->queue;
        unsigned int maxlen, nbytes;
        void *mem;
 
@@ -513,11 +1049,11 @@ static void uvc_video_decode_data(struct uvc_streaming *stream,
                return;
 
        /* Copy the video data to the buffer. */
-       maxlen = buf->buf.length - buf->buf.bytesused;
-       mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+       maxlen = buf->length - buf->bytesused;
+       mem = buf->mem + buf->bytesused;
        nbytes = min((unsigned int)len, maxlen);
        memcpy(mem, data, nbytes);
-       buf->buf.bytesused += nbytes;
+       buf->bytesused += nbytes;
 
        /* Complete the current frame if the buffer size was exceeded. */
        if (len > maxlen) {
@@ -530,7 +1066,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream,
                struct uvc_buffer *buf, const __u8 *data, int len)
 {
        /* Mark the buffer as done if the EOF marker is set. */
-       if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) {
+       if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
                uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
                if (data[0] == len)
                        uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
@@ -568,8 +1104,8 @@ static int uvc_video_encode_data(struct uvc_streaming *stream,
        void *mem;
 
        /* Copy video data to the URB buffer. */
-       mem = queue->mem + buf->buf.m.offset + queue->buf_used;
-       nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+       mem = buf->mem + queue->buf_used;
+       nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
        nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size,
                        nbytes);
        memcpy(data, mem, nbytes);
@@ -624,7 +1160,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
                        urb->iso_frame_desc[i].actual_length);
 
                if (buf->state == UVC_BUF_STATE_READY) {
-                       if (buf->buf.length != buf->buf.bytesused &&
+                       if (buf->length != buf->bytesused &&
                            !(stream->cur_format->flags &
                              UVC_FMT_FLAG_COMPRESSED))
                                buf->error = 1;
@@ -724,12 +1260,12 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
        stream->bulk.payload_size += ret;
        len -= ret;
 
-       if (buf->buf.bytesused == stream->queue.buf_used ||
+       if (buf->bytesused == stream->queue.buf_used ||
            stream->bulk.payload_size == stream->bulk.max_payload_size) {
-               if (buf->buf.bytesused == stream->queue.buf_used) {
+               if (buf->bytesused == stream->queue.buf_used) {
                        stream->queue.buf_used = 0;
                        buf->state = UVC_BUF_STATE_READY;
-                       buf->buf.sequence = ++stream->sequence;
+                       buf->buf.v4l2_buf.sequence = ++stream->sequence;
                        uvc_queue_next_buffer(&stream->queue, buf);
                        stream->last_fid ^= UVC_STREAM_FID;
                }
@@ -870,6 +1406,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
        struct urb *urb;
        unsigned int i;
 
+       uvc_video_stats_stop(stream);
+
        for (i = 0; i < UVC_URBS; ++i) {
                urb = stream->urb[i];
                if (urb == NULL)
@@ -882,6 +1420,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
 
        if (free_buffers)
                uvc_free_urb_buffers(stream);
+
+       uvc_video_clock_cleanup(stream);
 }
 
 /*
@@ -1009,6 +1549,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
        stream->bulk.skip_payload = 0;
        stream->bulk.payload_size = 0;
 
+       uvc_video_stats_start(stream);
+
+       ret = uvc_video_clock_init(stream);
+       if (ret < 0)
+               return ret;
+
        if (intf->num_altsetting > 1) {
                struct usb_host_endpoint *best_ep = NULL;
                unsigned int best_psize = 3 * 1024;
@@ -1283,6 +1829,11 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
                return ret;
        }
 
-       return uvc_init_video(stream, GFP_KERNEL);
-}
+       ret = uvc_init_video(stream, GFP_KERNEL);
+       if (ret < 0) {
+               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+               uvc_queue_enable(&stream->queue, 0);
+       }
 
+       return ret;
+}
index 4c1392ebcd4bd2634b245a23209f37c129e7be1f..67f88d85bb168b53e9dc9dd990c9d17fac1fd975 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/videodev2.h>
 #include <media/media-device.h>
 #include <media/v4l2-device.h>
+#include <media/videobuf2-core.h>
 
 /* --------------------------------------------------------------------------
  * UVC constants
 
 /* Maximum allowed number of control mappings per device */
 #define UVC_MAX_CONTROL_MAPPINGS       1024
+#define UVC_MAX_CONTROL_MENU_ENTRIES   32
 
 /* Devices quirks */
 #define UVC_QUIRK_STATUS_INTERVAL      0x00000001
@@ -319,35 +321,30 @@ enum uvc_buffer_state {
 };
 
 struct uvc_buffer {
-       unsigned long vma_use_count;
-       struct list_head stream;
-
-       /* Touched by interrupt handler. */
-       struct v4l2_buffer buf;
+       struct vb2_buffer buf;
        struct list_head queue;
-       wait_queue_head_t wait;
+
        enum uvc_buffer_state state;
        unsigned int error;
+
+       void *mem;
+       unsigned int length;
+       unsigned int bytesused;
+
+       u32 pts;
 };
 
-#define UVC_QUEUE_STREAMING            (1 << 0)
-#define UVC_QUEUE_DISCONNECTED         (1 << 1)
-#define UVC_QUEUE_DROP_CORRUPTED       (1 << 2)
+#define UVC_QUEUE_DISCONNECTED         (1 << 0)
+#define UVC_QUEUE_DROP_CORRUPTED       (1 << 1)
 
 struct uvc_video_queue {
-       enum v4l2_buf_type type;
+       struct vb2_queue queue;
+       struct mutex mutex;                     /* Protects queue */
 
-       void *mem;
        unsigned int flags;
-
-       unsigned int count;
-       unsigned int buf_size;
        unsigned int buf_used;
-       struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
-       struct mutex mutex;     /* protects buffers and mainqueue */
-       spinlock_t irqlock;     /* protects irqqueue */
 
-       struct list_head mainqueue;
+       spinlock_t irqlock;                     /* Protects irqqueue */
        struct list_head irqqueue;
 };
 
@@ -362,6 +359,51 @@ struct uvc_video_chain {
        struct mutex ctrl_mutex;                /* Protects ctrl.info */
 };
 
+struct uvc_stats_frame {
+       unsigned int size;              /* Number of bytes captured */
+       unsigned int first_data;        /* Index of the first non-empty packet */
+
+       unsigned int nb_packets;        /* Number of packets */
+       unsigned int nb_empty;          /* Number of empty packets */
+       unsigned int nb_invalid;        /* Number of packets with an invalid header */
+       unsigned int nb_errors;         /* Number of packets with the error bit set */
+
+       unsigned int nb_pts;            /* Number of packets with a PTS timestamp */
+       unsigned int nb_pts_diffs;      /* Number of PTS differences inside a frame */
+       unsigned int last_pts_diff;     /* Index of the last PTS difference */
+       bool has_initial_pts;           /* Whether the first non-empty packet has a PTS */
+       bool has_early_pts;             /* Whether a PTS is present before the first non-empty packet */
+       u32 pts;                        /* PTS of the last packet */
+
+       unsigned int nb_scr;            /* Number of packets with a SCR timestamp */
+       unsigned int nb_scr_diffs;      /* Number of SCR.STC differences inside a frame */
+       u16 scr_sof;                    /* SCR.SOF of the last packet */
+       u32 scr_stc;                    /* SCR.STC of the last packet */
+};
+
+struct uvc_stats_stream {
+       struct timespec start_ts;       /* Stream start timestamp */
+       struct timespec stop_ts;        /* Stream stop timestamp */
+
+       unsigned int nb_frames;         /* Number of frames */
+
+       unsigned int nb_packets;        /* Number of packets */
+       unsigned int nb_empty;          /* Number of empty packets */
+       unsigned int nb_invalid;        /* Number of packets with an invalid header */
+       unsigned int nb_errors;         /* Number of packets with the error bit set */
+
+       unsigned int nb_pts_constant;   /* Number of frames with constant PTS */
+       unsigned int nb_pts_early;      /* Number of frames with early PTS */
+       unsigned int nb_pts_initial;    /* Number of frames with initial PTS */
+
+       unsigned int nb_scr_count_ok;   /* Number of frames with at least one SCR per non empty packet */
+       unsigned int nb_scr_diffs_ok;   /* Number of frames with varying SCR.STC */
+       unsigned int scr_sof_count;     /* STC.SOF counter accumulated since stream start */
+       unsigned int scr_sof;           /* STC.SOF of the last packet */
+       unsigned int min_sof;           /* Minimum STC.SOF value */
+       unsigned int max_sof;           /* Maximum STC.SOF value */
+};
+
 struct uvc_streaming {
        struct list_head list;
        struct uvc_device *dev;
@@ -387,6 +429,7 @@ struct uvc_streaming {
         */
        struct mutex mutex;
 
+       /* Buffers queue. */
        unsigned int frozen : 1;
        struct uvc_video_queue queue;
        void (*decode) (struct urb *urb, struct uvc_streaming *video,
@@ -408,6 +451,32 @@ struct uvc_streaming {
 
        __u32 sequence;
        __u8 last_fid;
+
+       /* debugfs */
+       struct dentry *debugfs_dir;
+       struct {
+               struct uvc_stats_frame frame;
+               struct uvc_stats_stream stream;
+       } stats;
+
+       /* Timestamps support. */
+       struct uvc_clock {
+               struct uvc_clock_sample {
+                       u32 dev_stc;
+                       u16 dev_sof;
+                       struct timespec host_ts;
+                       u16 host_sof;
+               } *samples;
+
+               unsigned int head;
+               unsigned int count;
+               unsigned int size;
+
+               u16 last_sof;
+               u16 sof_offset;
+
+               spinlock_t lock;
+       } clock;
 };
 
 enum uvc_device_state {
@@ -479,9 +548,12 @@ struct uvc_driver {
 #define UVC_TRACE_SUSPEND      (1 << 8)
 #define UVC_TRACE_STATUS       (1 << 9)
 #define UVC_TRACE_VIDEO                (1 << 10)
+#define UVC_TRACE_STATS                (1 << 11)
+#define UVC_TRACE_CLOCK                (1 << 12)
 
 #define UVC_WARN_MINMAX                0
 #define UVC_WARN_PROBE_DEF     1
+#define UVC_WARN_XU_GET_RES    2
 
 extern unsigned int uvc_clock_param;
 extern unsigned int uvc_no_drop_param;
@@ -516,8 +588,8 @@ extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 extern void uvc_queue_init(struct uvc_video_queue *queue,
                enum v4l2_buf_type type, int drop_corrupted);
 extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
-               unsigned int nbuffers, unsigned int buflength);
-extern int uvc_free_buffers(struct uvc_video_queue *queue);
+               struct v4l2_requestbuffers *rb);
+extern void uvc_free_buffers(struct uvc_video_queue *queue);
 extern int uvc_query_buffer(struct uvc_video_queue *queue,
                struct v4l2_buffer *v4l2_buf);
 extern int uvc_queue_buffer(struct uvc_video_queue *queue,
@@ -539,7 +611,7 @@ extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
 extern int uvc_queue_allocated(struct uvc_video_queue *queue);
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 {
-       return queue->flags & UVC_QUEUE_STREAMING;
+       return vb2_is_streaming(&queue->queue);
 }
 
 /* V4L2 interface */
@@ -556,10 +628,11 @@ extern int uvc_video_resume(struct uvc_streaming *stream, int reset);
 extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
 extern int uvc_probe_video(struct uvc_streaming *stream,
                struct uvc_streaming_control *probe);
-extern int uvc_commit_video(struct uvc_streaming *stream,
-               struct uvc_streaming_control *ctrl);
 extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
                __u8 intfnum, __u8 cs, void *data, __u16 size);
+void uvc_video_clock_update(struct uvc_streaming *stream,
+                           struct v4l2_buffer *v4l2_buf,
+                           struct uvc_buffer *buf);
 
 /* Status */
 extern int uvc_status_init(struct uvc_device *dev);
@@ -612,4 +685,13 @@ extern struct usb_host_endpoint *uvc_find_endpoint(
 void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
                struct uvc_buffer *buf);
 
+/* debugfs and statistics */
+int uvc_debugfs_init(void);
+void uvc_debugfs_cleanup(void);
+int uvc_debugfs_init_stream(struct uvc_streaming *stream);
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+                           size_t size);
+
 #endif
index c68531b882794d46abfa260f378b1f4b3ec9f9c7..af4419e6c65855eca787bd4a61777f33cf5b0c7f 100644 (file)
@@ -985,6 +985,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_CROPCAP:
        case VIDIOC_G_CROP:
        case VIDIOC_S_CROP:
+       case VIDIOC_G_SELECTION:
+       case VIDIOC_S_SELECTION:
        case VIDIOC_G_JPEGCOMP:
        case VIDIOC_S_JPEGCOMP:
        case VIDIOC_QUERYSTD:
index 0f415dade05ae4bec936b2300f9c81e93fa535eb..da1f4c2d2d4b8d217cd2e3dafc716b88a25ef762 100644 (file)
@@ -467,6 +467,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_ILLUMINATORS_2:           return "Illuminator 2";
        case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:  return "Minimum Number of Capture Buffers";
        case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:   return "Minimum Number of Output Buffers";
+       case V4L2_CID_ALPHA_COMPONENT:          return "Alpha Component";
 
        /* MPEG controls */
        /* Keep the order of the 'case's the same as in videodev2.h! */
@@ -1108,8 +1109,8 @@ int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
        INIT_LIST_HEAD(&hdl->ctrls);
        INIT_LIST_HEAD(&hdl->ctrl_refs);
        hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
-       hdl->buckets = kzalloc(sizeof(hdl->buckets[0]) * hdl->nr_of_buckets,
-                                                               GFP_KERNEL);
+       hdl->buckets = kcalloc(hdl->nr_of_buckets, sizeof(hdl->buckets[0]),
+                              GFP_KERNEL);
        hdl->error = hdl->buckets ? 0 : -ENOMEM;
        return hdl->error;
 }
index a5c9ed128b974aaac3e4cba8ac03e4a2292d77d4..96e9615663e9d912b8868719b7c53d5ca73cfae6 100644 (file)
@@ -146,10 +146,9 @@ static void v4l2_device_release(struct device *cd)
        struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
 
        mutex_lock(&videodev_lock);
-       if (video_device[vdev->minor] != vdev) {
-               mutex_unlock(&videodev_lock);
+       if (WARN_ON(video_device[vdev->minor] != vdev)) {
                /* should not happen */
-               WARN_ON(1);
+               mutex_unlock(&videodev_lock);
                return;
        }
 
@@ -168,7 +167,7 @@ static void v4l2_device_release(struct device *cd)
        mutex_unlock(&videodev_lock);
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+       if (v4l2_dev && v4l2_dev->mdev &&
            vdev->vfl_type != VFL_TYPE_SUBDEV)
                media_device_unregister_entity(&vdev->entity);
 #endif
@@ -556,8 +555,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
        vdev->minor = -1;
 
        /* the release callback MUST be present */
-       WARN_ON(!vdev->release);
-       if (!vdev->release)
+       if (WARN_ON(!vdev->release))
                return -EINVAL;
 
        /* v4l2_fh support */
@@ -703,8 +701,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
            vdev->vfl_type != VFL_TYPE_SUBDEV) {
                vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
                vdev->entity.name = vdev->name;
-               vdev->entity.v4l.major = VIDEO_MAJOR;
-               vdev->entity.v4l.minor = vdev->minor;
+               vdev->entity.info.v4l.major = VIDEO_MAJOR;
+               vdev->entity.info.v4l.minor = vdev->minor;
                ret = media_device_register_entity(vdev->v4l2_dev->mdev,
                        &vdev->entity);
                if (ret < 0)
index 0edd618b9ddf17c1a117b157428df48ceccca1ae..1f203b85a63739463a448259800b31f240359bbf 100644 (file)
@@ -234,8 +234,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
                        goto clean_up;
                }
 #if defined(CONFIG_MEDIA_CONTROLLER)
-               sd->entity.v4l.major = VIDEO_MAJOR;
-               sd->entity.v4l.minor = vdev->minor;
+               sd->entity.info.v4l.major = VIDEO_MAJOR;
+               sd->entity.info.v4l.minor = vdev->minor;
 #endif
                sd->devnode = vdev;
        }
index e1da8fc9dd2f192e4451318bdc66a93fbea3279d..77feeb67e2db389334e186299c882ce4fd87e847 100644 (file)
@@ -238,6 +238,8 @@ static const char *v4l2_ioctls[] = {
        [_IOC_NR(VIDIOC_CROPCAP)]          = "VIDIOC_CROPCAP",
        [_IOC_NR(VIDIOC_G_CROP)]           = "VIDIOC_G_CROP",
        [_IOC_NR(VIDIOC_S_CROP)]           = "VIDIOC_S_CROP",
+       [_IOC_NR(VIDIOC_G_SELECTION)]      = "VIDIOC_G_SELECTION",
+       [_IOC_NR(VIDIOC_S_SELECTION)]      = "VIDIOC_S_SELECTION",
        [_IOC_NR(VIDIOC_G_JPEGCOMP)]       = "VIDIOC_G_JPEGCOMP",
        [_IOC_NR(VIDIOC_S_JPEGCOMP)]       = "VIDIOC_S_JPEGCOMP",
        [_IOC_NR(VIDIOC_QUERYSTD)]         = "VIDIOC_QUERYSTD",
@@ -1547,11 +1549,32 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_crop *p = arg;
 
-               if (!ops->vidioc_g_crop)
+               if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
                        break;
 
                dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               ret = ops->vidioc_g_crop(file, fh, p);
+
+               if (ops->vidioc_g_crop) {
+                       ret = ops->vidioc_g_crop(file, fh, p);
+               } else {
+                       /* simulate capture crop using selection api */
+                       struct v4l2_selection s = {
+                               .type = p->type,
+                       };
+
+                       /* crop means compose for output devices */
+                       if (V4L2_TYPE_IS_OUTPUT(p->type))
+                               s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+                       else
+                               s.target = V4L2_SEL_TGT_CROP_ACTIVE;
+
+                       ret = ops->vidioc_g_selection(file, fh, &s);
+
+                       /* copying results to old structure on success */
+                       if (!ret)
+                               p->c = s.r;
+               }
+
                if (!ret)
                        dbgrect(vfd, "", &p->c);
                break;
@@ -1560,15 +1583,65 @@ static long __video_do_ioctl(struct file *file,
        {
                struct v4l2_crop *p = arg;
 
-               if (!ops->vidioc_s_crop)
+               if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
                        break;
+
                if (ret_prio) {
                        ret = ret_prio;
                        break;
                }
                dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
                dbgrect(vfd, "", &p->c);
-               ret = ops->vidioc_s_crop(file, fh, p);
+
+               if (ops->vidioc_s_crop) {
+                       ret = ops->vidioc_s_crop(file, fh, p);
+               } else {
+                       /* simulate capture crop using selection api */
+                       struct v4l2_selection s = {
+                               .type = p->type,
+                               .r = p->c,
+                       };
+
+                       /* crop means compose for output devices */
+                       if (V4L2_TYPE_IS_OUTPUT(p->type))
+                               s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+                       else
+                               s.target = V4L2_SEL_TGT_CROP_ACTIVE;
+
+                       ret = ops->vidioc_s_selection(file, fh, &s);
+               }
+               break;
+       }
+       case VIDIOC_G_SELECTION:
+       {
+               struct v4l2_selection *p = arg;
+
+               if (!ops->vidioc_g_selection)
+                       break;
+
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+
+               ret = ops->vidioc_g_selection(file, fh, p);
+               if (!ret)
+                       dbgrect(vfd, "", &p->r);
+               break;
+       }
+       case VIDIOC_S_SELECTION:
+       {
+               struct v4l2_selection *p = arg;
+
+               if (!ops->vidioc_s_selection)
+                       break;
+
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
+
+               dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+               dbgrect(vfd, "", &p->r);
+
+               ret = ops->vidioc_s_selection(file, fh, p);
                break;
        }
        case VIDIOC_CROPCAP:
@@ -1576,11 +1649,42 @@ static long __video_do_ioctl(struct file *file,
                struct v4l2_cropcap *p = arg;
 
                /*FIXME: Should also show v4l2_fract pixelaspect */
-               if (!ops->vidioc_cropcap)
+               if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
                        break;
 
                dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-               ret = ops->vidioc_cropcap(file, fh, p);
+               if (ops->vidioc_cropcap) {
+                       ret = ops->vidioc_cropcap(file, fh, p);
+               } else {
+                       struct v4l2_selection s = { .type = p->type };
+
+                       /* obtaining bounds */
+                       if (V4L2_TYPE_IS_OUTPUT(p->type))
+                               s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+                       else
+                               s.target = V4L2_SEL_TGT_CROP_BOUNDS;
+
+                       ret = ops->vidioc_g_selection(file, fh, &s);
+                       if (ret)
+                               break;
+                       p->bounds = s.r;
+
+                       /* obtaining defrect */
+                       if (V4L2_TYPE_IS_OUTPUT(p->type))
+                               s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+                       else
+                               s.target = V4L2_SEL_TGT_CROP_DEFAULT;
+
+                       ret = ops->vidioc_g_selection(file, fh, &s);
+                       if (ret)
+                               break;
+                       p->defrect = s.r;
+
+                       /* setting trivial pixelaspect */
+                       p->pixelaspect.numerator = 1;
+                       p->pixelaspect.denominator = 1;
+               }
+
                if (!ret) {
                        dbgrect(vfd, "bounds ", &p->bounds);
                        dbgrect(vfd, "defrect ", &p->defrect);
@@ -2226,6 +2330,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                struct v4l2_ext_controls *ctrls = parg;
 
                if (ctrls->count != 0) {
+                       if (ctrls->count > V4L2_CID_MAX_CTRLS) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        *user_ptr = (void __user *)ctrls->controls;
                        *kernel_ptr = (void *)&ctrls->controls;
                        *array_size = sizeof(struct v4l2_ext_control)
index 65ade5f03c2ef56efa5331c58a44391caa30f2ac..41d118ee2de63860fdac7b9eba76c1c4cf318c13 100644 (file)
@@ -193,6 +193,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                return v4l2_subdev_call(sd, core, s_register, p);
        }
 #endif
+
+       case VIDIOC_LOG_STATUS:
+               return v4l2_subdev_call(sd, core, log_status);
+
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
        case VIDIOC_SUBDEV_G_FMT: {
                struct v4l2_subdev_format *format = arg;
index bfae41ba53c381dce8f1e0b7bd0b602325a040d7..20f7237b824213537f55b33a86edc467fe44f433 100644 (file)
@@ -156,14 +156,10 @@ static struct via_format {
                .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
                .bpp            = 2,
        },
-       {
-               .desc           = "RGB 565",
-               .pixelformat    = V4L2_PIX_FMT_RGB565,
-               .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
-               .bpp            = 2,
-       },
        /* RGB444 and Bayer should be doable, but have never been
-          tested with this driver. */
+          tested with this driver. RGB565 seems to work at the default
+          resolution, but results in color corruption when being scaled by
+          viacam_set_scaled(), and is disabled as a result. */
 };
 #define N_VIA_FMTS ARRAY_SIZE(via_formats)
 
@@ -1504,14 +1500,4 @@ static struct platform_driver viacam_driver = {
        .remove = viacam_remove,
 };
 
-static int viacam_init(void)
-{
-       return platform_driver_register(&viacam_driver);
-}
-module_init(viacam_init);
-
-static void viacam_exit(void)
-{
-       platform_driver_unregister(&viacam_driver);
-}
-module_exit(viacam_exit);
+module_platform_driver(viacam_driver);
index 3de7c7e4402de7f461c1eb4a41bde553f9062ada..59cb54aa2946e24cf29ae08846684d20c896642d 100644 (file)
@@ -226,9 +226,10 @@ static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter,
        }
 
        /* register network adapter */
-       dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
-       if (dvb->net.dvbdev == NULL) {
-               result = -ENOMEM;
+       result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_net_init failed (errno = %d)\n",
+                      dvb->name, result);
                goto fail_fe_conn;
        }
        return 0;
index 95a3f5e82aef14c74a81045baa26874eb008e7c1..2e8f1df775b622ef9f877be16916fd7d9d0e0c80 100644 (file)
@@ -30,7 +30,7 @@ module_param(debug, int, 0644);
                        printk(KERN_DEBUG "vb2: " fmt, ## arg);         \
        } while (0)
 
-#define call_memop(q, plane, op, args...)                              \
+#define call_memop(q, op, args...)                                     \
        (((q)->mem_ops->op) ?                                           \
                ((q)->mem_ops->op(args)) : 0)
 
@@ -52,7 +52,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
        /* Allocate memory for all planes in this buffer */
        for (plane = 0; plane < vb->num_planes; ++plane) {
-               mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
+               mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
                                      q->plane_sizes[plane]);
                if (IS_ERR_OR_NULL(mem_priv))
                        goto free;
@@ -65,8 +65,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
        return 0;
 free:
        /* Free already allocated memory if one of the allocations failed */
-       for (; plane > 0; --plane)
-               call_memop(q, plane, put, vb->planes[plane - 1].mem_priv);
+       for (; plane > 0; --plane) {
+               call_memop(q, put, vb->planes[plane - 1].mem_priv);
+               vb->planes[plane - 1].mem_priv = NULL;
+       }
 
        return -ENOMEM;
 }
@@ -80,10 +82,10 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
        unsigned int plane;
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
-               call_memop(q, plane, put, vb->planes[plane].mem_priv);
+               call_memop(q, put, vb->planes[plane].mem_priv);
                vb->planes[plane].mem_priv = NULL;
-               dprintk(3, "Freed plane %d of buffer %d\n",
-                               plane, vb->v4l2_buf.index);
+               dprintk(3, "Freed plane %d of buffer %d\n", plane,
+                       vb->v4l2_buf.index);
        }
 }
 
@@ -97,12 +99,9 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
        unsigned int plane;
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
-               void *mem_priv = vb->planes[plane].mem_priv;
-
-               if (mem_priv) {
-                       call_memop(q, plane, put_userptr, mem_priv);
-                       vb->planes[plane].mem_priv = NULL;
-               }
+               if (vb->planes[plane].mem_priv)
+                       call_memop(q, put_userptr, vb->planes[plane].mem_priv);
+               vb->planes[plane].mem_priv = NULL;
        }
 }
 
@@ -305,7 +304,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
                 * case anyway. If num_users() returns more than 1,
                 * we are not the only user of the plane's memory.
                 */
-               if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1)
+               if (mem_priv && call_memop(q, num_users, mem_priv) > 1)
                        return true;
        }
        return false;
@@ -731,10 +730,10 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
 {
        struct vb2_queue *q = vb->vb2_queue;
 
-       if (plane_no > vb->num_planes)
+       if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
                return NULL;
 
-       return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv);
+       return call_memop(q, vaddr, vb->planes[plane_no].mem_priv);
 
 }
 EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
@@ -754,10 +753,10 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
 {
        struct vb2_queue *q = vb->vb2_queue;
 
-       if (plane_no > vb->num_planes)
+       if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
                return NULL;
 
-       return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv);
+       return call_memop(q, cookie, vb->planes[plane_no].mem_priv);
 }
 EXPORT_SYMBOL_GPL(vb2_plane_cookie);
 
@@ -883,7 +882,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                /* Skip the plane if already verified */
-               if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
+               if (vb->v4l2_planes[plane].m.userptr &&
+                   vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
                    && vb->v4l2_planes[plane].length == planes[plane].length)
                        continue;
 
@@ -898,27 +898,23 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
                /* Release previously acquired memory if present */
                if (vb->planes[plane].mem_priv)
-                       call_memop(q, plane, put_userptr,
-                                       vb->planes[plane].mem_priv);
+                       call_memop(q, put_userptr, vb->planes[plane].mem_priv);
 
                vb->planes[plane].mem_priv = NULL;
                vb->v4l2_planes[plane].m.userptr = 0;
                vb->v4l2_planes[plane].length = 0;
 
                /* Acquire each plane's memory */
-               if (q->mem_ops->get_userptr) {
-                       mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane],
-                                                       planes[plane].m.userptr,
-                                                       planes[plane].length,
-                                                       write);
-                       if (IS_ERR(mem_priv)) {
-                               dprintk(1, "qbuf: failed acquiring userspace "
+               mem_priv = call_memop(q, get_userptr, q->alloc_ctx[plane],
+                                     planes[plane].m.userptr,
+                                     planes[plane].length, write);
+               if (IS_ERR_OR_NULL(mem_priv)) {
+                       dprintk(1, "qbuf: failed acquiring userspace "
                                                "memory for plane %d\n", plane);
-                               ret = PTR_ERR(mem_priv);
-                               goto err;
-                       }
-                       vb->planes[plane].mem_priv = mem_priv;
+                       ret = mem_priv ? PTR_ERR(mem_priv) : -EINVAL;
+                       goto err;
                }
+               vb->planes[plane].mem_priv = mem_priv;
        }
 
        /*
@@ -943,8 +939,7 @@ err:
        /* In case of errors, release planes that were already acquired */
        for (plane = 0; plane < vb->num_planes; ++plane) {
                if (vb->planes[plane].mem_priv)
-                       call_memop(q, plane, put_userptr,
-                                  vb->planes[plane].mem_priv);
+                       call_memop(q, put_userptr, vb->planes[plane].mem_priv);
                vb->planes[plane].mem_priv = NULL;
                vb->v4l2_planes[plane].m.userptr = 0;
                vb->v4l2_planes[plane].length = 0;
@@ -1081,46 +1076,76 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf);
  */
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
+       struct rw_semaphore *mmap_sem = NULL;
        struct vb2_buffer *vb;
-       int ret;
+       int ret = 0;
+
+       /*
+        * In case of user pointer buffers vb2 allocator needs to get direct
+        * access to userspace pages. This requires getting read access on
+        * mmap semaphore in the current process structure. The same
+        * semaphore is taken before calling mmap operation, while both mmap
+        * and qbuf are called by the driver or v4l2 core with driver's lock
+        * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in
+        * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core
+        * release driver's lock, takes mmap_sem and then takes again driver's
+        * lock.
+        *
+        * To avoid race with other vb2 calls, which might be called after
+        * releasing driver's lock, this operation is performed at the
+        * beggining of qbuf processing. This way the queue status is
+        * consistent after getting driver's lock back.
+        */
+       if (q->memory == V4L2_MEMORY_USERPTR) {
+               mmap_sem = &current->mm->mmap_sem;
+               call_qop(q, wait_prepare, q);
+               down_read(mmap_sem);
+               call_qop(q, wait_finish, q);
+       }
 
        if (q->fileio) {
                dprintk(1, "qbuf: file io in progress\n");
-               return -EBUSY;
+               ret = -EBUSY;
+               goto unlock;
        }
 
        if (b->type != q->type) {
                dprintk(1, "qbuf: invalid buffer type\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        if (b->index >= q->num_buffers) {
                dprintk(1, "qbuf: buffer index out of range\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        vb = q->bufs[b->index];
        if (NULL == vb) {
                /* Should never happen */
                dprintk(1, "qbuf: buffer is NULL\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        if (b->memory != q->memory) {
                dprintk(1, "qbuf: invalid memory type\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        switch (vb->state) {
        case VB2_BUF_STATE_DEQUEUED:
                ret = __buf_prepare(vb, b);
                if (ret)
-                       return ret;
+                       goto unlock;
        case VB2_BUF_STATE_PREPARED:
                break;
        default:
                dprintk(1, "qbuf: buffer already in use\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        /*
@@ -1141,7 +1166,10 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
        __fill_v4l2_buffer(vb, b);
 
        dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
-       return 0;
+unlock:
+       if (mmap_sem)
+               up_read(mmap_sem);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(vb2_qbuf);
 
@@ -1521,7 +1549,6 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 {
        unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
-       struct vb2_plane *vb_plane;
        struct vb2_buffer *vb;
        unsigned int buffer, plane;
        int ret;
@@ -1558,9 +1585,8 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
                return ret;
 
        vb = q->bufs[buffer];
-       vb_plane = &vb->planes[plane];
 
-       ret = q->mem_ops->mmap(vb_plane->mem_priv, vma);
+       ret = call_memop(q, mmap, vb->planes[plane].mem_priv, vma);
        if (ret)
                return ret;
 
index 3bad8b105fea3260ffcb5fff745009b943885eec..25c3b360e1adf1cdfdce19f80c59f847d38f18b4 100644 (file)
@@ -140,7 +140,6 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
        if (!buf->pages)
                goto userptr_fail_pages_array_alloc;
 
-       down_read(&current->mm->mmap_sem);
        num_pages_from_user = get_user_pages(current, current->mm,
                                             vaddr & PAGE_MASK,
                                             buf->sg_desc.num_pages,
@@ -148,7 +147,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
                                             1, /* force */
                                             buf->pages,
                                             NULL);
-       up_read(&current->mm->mmap_sem);
+
        if (num_pages_from_user != buf->sg_desc.num_pages)
                goto userptr_fail_get_user_pages;
 
index 71a7a78c3fc05ce039b87661644f880ea15b4a79..c41cb60245d6c0b593f4614f3baeb2a7b88bc4f2 100644 (file)
@@ -100,29 +100,26 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
        unsigned long offset, start, end;
        unsigned long this_pfn, prev_pfn;
        dma_addr_t pa = 0;
-       int ret = -EFAULT;
 
        start = vaddr;
        offset = start & ~PAGE_MASK;
        end = start + size;
 
-       down_read(&mm->mmap_sem);
        vma = find_vma(mm, start);
 
        if (vma == NULL || vma->vm_end < end)
-               goto done;
+               return -EFAULT;
 
        for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
-               ret = follow_pfn(vma, start, &this_pfn);
+               int ret = follow_pfn(vma, start, &this_pfn);
                if (ret)
-                       goto done;
+                       return ret;
 
                if (prev_pfn == 0)
                        pa = this_pfn << PAGE_SHIFT;
-               else if (this_pfn != prev_pfn + 1) {
-                       ret = -EFAULT;
-                       goto done;
-               }
+               else if (this_pfn != prev_pfn + 1)
+                       return -EFAULT;
+
                prev_pfn = this_pfn;
        }
 
@@ -130,16 +127,11 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
         * Memory is contigous, lock vma and return to the caller
         */
        *res_vma = vb2_get_vma(vma);
-       if (*res_vma == NULL) {
-               ret = -ENOMEM;
-               goto done;
-       }
-       *res_pa = pa + offset;
-       ret = 0;
+       if (*res_vma == NULL)
+               return -ENOMEM;
 
-done:
-       up_read(&mm->mmap_sem);
-       return ret;
+       *res_pa = pa + offset;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
 
index a3a884234059afcacae18bd2e246190bfcfa5970..4e789a178f8a810ca5ec6341e5d1db9d2ae34ce7 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 
 struct vb2_vmalloc_buf {
        void                            *vaddr;
+       struct page                     **pages;
+       int                             write;
        unsigned long                   size;
+       unsigned int                    n_pages;
        atomic_t                        refcount;
        struct vb2_vmarea_handler       handler;
 };
@@ -31,7 +35,7 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
 {
        struct vb2_vmalloc_buf *buf;
 
-       buf = kzalloc(sizeof *buf, GFP_KERNEL);
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
        if (!buf)
                return NULL;
 
@@ -42,15 +46,12 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
        buf->handler.arg = buf;
 
        if (!buf->vaddr) {
-               printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size);
+               pr_debug("vmalloc of size %ld failed\n", buf->size);
                kfree(buf);
                return NULL;
        }
 
        atomic_inc(&buf->refcount);
-       printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n",
-                       buf->size, buf->vaddr);
-
        return buf;
 }
 
@@ -59,21 +60,84 @@ static void vb2_vmalloc_put(void *buf_priv)
        struct vb2_vmalloc_buf *buf = buf_priv;
 
        if (atomic_dec_and_test(&buf->refcount)) {
-               printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n",
-                       __func__, buf->vaddr);
                vfree(buf->vaddr);
                kfree(buf);
        }
 }
 
-static void *vb2_vmalloc_vaddr(void *buf_priv)
+static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+                                    unsigned long size, int write)
+{
+       struct vb2_vmalloc_buf *buf;
+       unsigned long first, last;
+       int n_pages, offset;
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->write = write;
+       offset = vaddr & ~PAGE_MASK;
+       buf->size = size;
+
+       first = vaddr >> PAGE_SHIFT;
+       last  = (vaddr + size - 1) >> PAGE_SHIFT;
+       buf->n_pages = last - first + 1;
+       buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL);
+       if (!buf->pages)
+               goto fail_pages_array_alloc;
+
+       /* current->mm->mmap_sem is taken by videobuf2 core */
+       n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK,
+                                buf->n_pages, write, 1, /* force */
+                                buf->pages, NULL);
+       if (n_pages != buf->n_pages)
+               goto fail_get_user_pages;
+
+       buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL);
+       if (!buf->vaddr)
+               goto fail_get_user_pages;
+
+       buf->vaddr += offset;
+       return buf;
+
+fail_get_user_pages:
+       pr_debug("get_user_pages requested/got: %d/%d]\n", n_pages,
+                buf->n_pages);
+       while (--n_pages >= 0)
+               put_page(buf->pages[n_pages]);
+       kfree(buf->pages);
+
+fail_pages_array_alloc:
+       kfree(buf);
+
+       return NULL;
+}
+
+static void vb2_vmalloc_put_userptr(void *buf_priv)
 {
        struct vb2_vmalloc_buf *buf = buf_priv;
+       unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK;
+       unsigned int i;
+
+       if (vaddr)
+               vm_unmap_ram((void *)vaddr, buf->n_pages);
+       for (i = 0; i < buf->n_pages; ++i) {
+               if (buf->write)
+                       set_page_dirty_lock(buf->pages[i]);
+               put_page(buf->pages[i]);
+       }
+       kfree(buf->pages);
+       kfree(buf);
+}
 
-       BUG_ON(!buf);
+static void *vb2_vmalloc_vaddr(void *buf_priv)
+{
+       struct vb2_vmalloc_buf *buf = buf_priv;
 
        if (!buf->vaddr) {
-               printk(KERN_ERR "Address of an unallocated plane requested\n");
+               pr_err("Address of an unallocated plane requested "
+                      "or cannot map user pointer\n");
                return NULL;
        }
 
@@ -92,13 +156,13 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
        int ret;
 
        if (!buf) {
-               printk(KERN_ERR "No memory to map\n");
+               pr_err("No memory to map\n");
                return -EINVAL;
        }
 
        ret = remap_vmalloc_range(vma, buf->vaddr, 0);
        if (ret) {
-               printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret);
+               pr_err("Remapping vmalloc memory, error: %d\n", ret);
                return ret;
        }
 
@@ -121,6 +185,8 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
 const struct vb2_mem_ops vb2_vmalloc_memops = {
        .alloc          = vb2_vmalloc_alloc,
        .put            = vb2_vmalloc_put,
+       .get_userptr    = vb2_vmalloc_get_userptr,
+       .put_userptr    = vb2_vmalloc_put_userptr,
        .vaddr          = vb2_vmalloc_vaddr,
        .mmap           = vb2_vmalloc_mmap,
        .num_users      = vb2_vmalloc_num_users,
index 52a0a3736c820d156025c8fc91df13d20cb31663..4d7391ec80013279d965db1070f978f3948cf241 100644 (file)
@@ -708,7 +708,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb,
                size, count);
 
        /* allocate memory for table with virtual (page) addresses */
-       fb->desc_table.virtual = (unsigned long *)
+       fb->desc_table.virtual =
                kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
        if (!fb->desc_table.virtual)
                return -ENOMEM;
index 5865029db0f67999404c6789b087de4f46612045..28aba00dc6295c5742551813fbf792033412c6ca 100644 (file)
@@ -1,6 +1,7 @@
 config DVB_AS102
        tristate "Abilis AS102 DVB receiver"
        depends on DVB_CORE && USB && I2C && INPUT
+       select FW_LOADER
        help
          Choose Y or M here if you have a device containing an AS102
 
index e7dbb6f814d53c62a24d21bcc83f7ad221d1c6e1..1bca43e847c7c0c301e6d711ea128e96e7db58c5 100644 (file)
@@ -3,4 +3,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \
 
 obj-$(CONFIG_DVB_AS102) += dvb-as102.o
 
-EXTRA_CFLAGS += -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
index 828526d4c28985221e6b6ebba019053e1a137d21..aae0505a36c4ada7cedaafa28074971f42cb76f7 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/kref.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 
 /* header file for Usb device driver*/
@@ -56,13 +56,11 @@ int elna_enable = 1;
 module_param_named(elna_enable, elna_enable, int, 0644);
 MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
 
-#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-#endif
 
 static void as102_stop_stream(struct as102_dev_t *dev)
 {
-       struct as102_bus_adapter_t *bus_adap;
+       struct as10x_bus_adapter_t *bus_adap;
 
        if (dev != NULL)
                bus_adap = &dev->bus_adap;
@@ -85,7 +83,7 @@ static void as102_stop_stream(struct as102_dev_t *dev)
 
 static int as102_start_stream(struct as102_dev_t *dev)
 {
-       struct as102_bus_adapter_t *bus_adap;
+       struct as10x_bus_adapter_t *bus_adap;
        int ret = -EFAULT;
 
        if (dev != NULL)
@@ -111,7 +109,7 @@ static int as102_start_stream(struct as102_dev_t *dev)
 static int as10x_pid_filter(struct as102_dev_t *dev,
                            int index, u16 pid, int onoff) {
 
-       struct as102_bus_adapter_t *bus_adap = &dev->bus_adap;
+       struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
        int ret = -EFAULT;
 
        ENTER();
@@ -123,22 +121,22 @@ static int as10x_pid_filter(struct as102_dev_t *dev,
 
        switch (onoff) {
        case 0:
-           ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
-           dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
-                   index, pid, ret);
-           break;
+               ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
+               dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
+                       index, pid, ret);
+               break;
        case 1:
        {
-           struct as10x_ts_filter filter;
+               struct as10x_ts_filter filter;
 
-           filter.type = TS_PID_TYPE_TS;
-           filter.idx = 0xFF;
-           filter.pid = pid;
+               filter.type = TS_PID_TYPE_TS;
+               filter.idx = 0xFF;
+               filter.pid = pid;
 
-           ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
-           dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
-                   index, filter.idx, filter.pid, ret);
-           break;
+               ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
+               dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
+                       index, filter.idx, filter.pid, ret);
+               break;
        }
        }
 
@@ -159,10 +157,9 @@ static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
        if (mutex_lock_interruptible(&as102_dev->sem))
                return -ERESTARTSYS;
 
-       if (pid_filtering) {
-               as10x_pid_filter(as102_dev,
-                               dvbdmxfeed->index, dvbdmxfeed->pid, 1);
-       }
+       if (pid_filtering)
+               as10x_pid_filter(as102_dev, dvbdmxfeed->index,
+                                dvbdmxfeed->pid, 1);
 
        if (as102_dev->streaming++ == 0)
                ret = as102_start_stream(as102_dev);
@@ -185,10 +182,9 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        if (--as102_dev->streaming == 0)
                as102_stop_stream(as102_dev);
 
-       if (pid_filtering) {
-               as10x_pid_filter(as102_dev,
-                               dvbdmxfeed->index, dvbdmxfeed->pid, 0);
-       }
+       if (pid_filtering)
+               as10x_pid_filter(as102_dev, dvbdmxfeed->index,
+                                dvbdmxfeed->pid, 0);
 
        mutex_unlock(&as102_dev->sem);
        LEAVE();
@@ -197,27 +193,16 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 
 int as102_dvb_register(struct as102_dev_t *as102_dev)
 {
-       int ret = 0;
-       ENTER();
+       struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
+       int ret;
 
        ret = dvb_register_adapter(&as102_dev->dvb_adap,
-                                  as102_dev->name,
-                                  THIS_MODULE,
-#if defined(CONFIG_AS102_USB)
-                                  &as102_dev->bus_adap.usb_dev->dev
-#elif defined(CONFIG_AS102_SPI)
-                                  &as102_dev->bus_adap.spi_dev->dev
-#else
-#error >>> dvb_register_adapter <<<
-#endif
-#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
-                                  , adapter_nr
-#endif
-                                  );
+                          as102_dev->name, THIS_MODULE,
+                          dev, adapter_nr);
        if (ret < 0) {
-               err("%s: dvb_register_adapter() failed (errno = %d)",
-                   __func__, ret);
-               goto failed;
+               dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
+                       __func__, ret);
+               return ret;
        }
 
        as102_dev->dvb_dmx.priv = as102_dev;
@@ -235,22 +220,22 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
 
        ret = dvb_dmx_init(&as102_dev->dvb_dmx);
        if (ret < 0) {
-               err("%s: dvb_dmx_init() failed (errno = %d)", __func__, ret);
-               goto failed;
+               dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
+               goto edmxinit;
        }
 
        ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
        if (ret < 0) {
-               err("%s: dvb_dmxdev_init() failed (errno = %d)", __func__,
-                   ret);
-               goto failed;
+               dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
+                       __func__, ret);
+               goto edmxdinit;
        }
 
        ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
        if (ret < 0) {
-               err("%s: as102_dvb_register_frontend() failed (errno = %d)",
+               dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
                    __func__, ret);
-               goto failed;
+               goto efereg;
        }
 
        /* init bus mutex for token locking */
@@ -259,7 +244,6 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
        /* init start / stop stream mutex */
        mutex_init(&as102_dev->sem);
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
        /*
         * try to load as102 firmware. If firmware upload failed, we'll be
         * able to upload it later.
@@ -267,18 +251,21 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
        if (fw_upload)
                try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
                                "firmware_class");
-#endif
 
-failed:
-       LEAVE();
-       /* FIXME: free dvb_XXX */
+       pr_info("Registered device %s", as102_dev->name);
+       return 0;
+
+efereg:
+       dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
+edmxdinit:
+       dvb_dmx_release(&as102_dev->dvb_dmx);
+edmxinit:
+       dvb_unregister_adapter(&as102_dev->dvb_adap);
        return ret;
 }
 
 void as102_dvb_unregister(struct as102_dev_t *as102_dev)
 {
-       ENTER();
-
        /* unregister as102 frontend */
        as102_dvb_unregister_fe(&as102_dev->dvb_fe);
 
@@ -289,28 +276,18 @@ void as102_dvb_unregister(struct as102_dev_t *as102_dev)
        /* unregister dvb adapter */
        dvb_unregister_adapter(&as102_dev->dvb_adap);
 
-       LEAVE();
+       pr_info("Unregistered device %s", as102_dev->name);
 }
 
 static int __init as102_driver_init(void)
 {
-       int ret = 0;
-
-       ENTER();
+       int ret;
 
        /* register this driver with the low level subsystem */
-#if defined(CONFIG_AS102_USB)
        ret = usb_register(&as102_usb_driver);
        if (ret)
                err("usb_register failed (ret = %d)", ret);
-#endif
-#if defined(CONFIG_AS102_SPI)
-       ret = spi_register_driver(&as102_spi_driver);
-       if (ret)
-               printk(KERN_ERR "spi_register failed (ret = %d)", ret);
-#endif
 
-       LEAVE();
        return ret;
 }
 
@@ -327,15 +304,8 @@ module_init(as102_driver_init);
  */
 static void __exit as102_driver_exit(void)
 {
-       ENTER();
        /* deregister this driver with the low level bus subsystem */
-#if defined(CONFIG_AS102_USB)
        usb_deregister(&as102_usb_driver);
-#endif
-#if defined(CONFIG_AS102_SPI)
-       spi_unregister_driver(&as102_spi_driver);
-#endif
-       LEAVE();
 }
 
 /*
@@ -347,5 +317,3 @@ module_exit(as102_driver_exit);
 MODULE_DESCRIPTION(DRIVER_FULL_NAME);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index fd33f5a12dcc2167cf9dada508b13521f7159b8f..957f0ed0d81aae7c8d587dbca4b853cf862b3814 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#if defined(CONFIG_AS102_USB)
 #include <linux/usb.h>
-extern struct usb_driver as102_usb_driver;
-#endif
-
-#if defined(CONFIG_AS102_SPI)
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/cdev.h>
-
-extern struct spi_driver as102_spi_driver;
-#endif
-
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dmxdev.h"
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dmxdev.h>
+#include "as10x_cmd.h"
+#include "as102_usb_drv.h"
 
 #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
 #define DRIVER_NAME "as10x_usb"
 
 extern int as102_debug;
 #define debug  as102_debug
+extern struct usb_driver as102_usb_driver;
+extern int elna_enable;
 
 #define dprintk(debug, args...) \
        do { if (debug) {       \
-               printk(KERN_DEBUG "%s: ",__FUNCTION__); \
+               pr_debug("%s: ", __func__);     \
                printk(args);   \
        } } while (0)
 
 #ifdef TRACE
-#define ENTER()                 printk(">> enter %s\n", __FUNCTION__)
-#define LEAVE()                 printk("<< leave %s\n", __FUNCTION__)
+#define ENTER()        pr_debug(">> enter %s\n", __func__)
+#define LEAVE()        pr_debug("<< leave %s\n", __func__)
 #else
 #define ENTER()
 #define LEAVE()
@@ -59,39 +51,14 @@ extern int as102_debug;
 #define AS102_USB_BUF_SIZE     512
 #define MAX_STREAM_URB         32
 
-#include "as10x_cmd.h"
-
-#if defined(CONFIG_AS102_USB)
-#include "as102_usb_drv.h"
-#endif
-
-#if defined(CONFIG_AS102_SPI)
-#include "as10x_spi_drv.h"
-#endif
-
-
-struct as102_bus_adapter_t {
-#if defined(CONFIG_AS102_USB)
+struct as10x_bus_adapter_t {
        struct usb_device *usb_dev;
-#elif defined(CONFIG_AS102_SPI)
-       struct spi_device *spi_dev;
-       struct cdev cdev; /* spidev raw device */
-
-       struct timer_list timer;
-       struct completion xfer_done;
-#endif
        /* bus token lock */
        struct mutex lock;
        /* low level interface for bus adapter */
        union as10x_bus_token_t {
-#if defined(CONFIG_AS102_USB)
                /* usb token */
                struct as10x_usb_token_cmd_t usb;
-#endif
-#if defined(CONFIG_AS102_SPI)
-               /* spi token */
-               struct as10x_spi_token_cmd_t spi;
-#endif
        } token;
 
        /* token cmd xfer id */
@@ -106,7 +73,7 @@ struct as102_bus_adapter_t {
 
 struct as102_dev_t {
        const char *name;
-       struct as102_bus_adapter_t bus_adap;
+       struct as10x_bus_adapter_t bus_adap;
        struct list_head device_entry;
        struct kref kref;
        unsigned long minor;
@@ -138,5 +105,3 @@ void as102_dvb_unregister(struct as102_dev_t *dev);
 
 int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe);
 int as102_dvb_unregister_fe(struct dvb_frontend *dev);
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index 3550f905367e611d2d210619ad63733220588772..bdc5a38cddf7d3668c25a9e7a6e9683c18829957 100644 (file)
 #include "as10x_types.h"
 #include "as10x_cmd.h"
 
-extern int elna_enable;
-
-static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *dst,
                                         struct as10x_tps *src);
 
 static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
-                                         struct dvb_frontend_parameters *src);
+                                         struct dtv_frontend_properties *src);
 
-static int as102_fe_set_frontend(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *params)
+static int as102_fe_set_frontend(struct dvb_frontend *fe)
 {
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        int ret = 0;
        struct as102_dev_t *dev;
        struct as10x_tune_args tune_args = { 0 };
@@ -47,7 +45,7 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe,
        if (mutex_lock_interruptible(&dev->bus_adap.lock))
                return -EBUSY;
 
-       as102_fe_copy_tune_parameters(&tune_args, params);
+       as102_fe_copy_tune_parameters(&tune_args, p);
 
        /* send abilis command: SET_TUNE */
        ret =  as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
@@ -60,8 +58,9 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe,
        return (ret < 0) ? -EINVAL : 0;
 }
 
-static int as102_fe_get_frontend(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *p) {
+static int as102_fe_get_frontend(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        int ret = 0;
        struct as102_dev_t *dev;
        struct as10x_tps tps = { 0 };
@@ -280,9 +279,9 @@ static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
 }
 
 static struct dvb_frontend_ops as102_fe_ops = {
+       .delsys = { SYS_DVBT },
        .info = {
                .name                   = "Unknown AS102 device",
-               .type                   = FE_OFDM,
                .frequency_min          = 174000000,
                .frequency_max          = 862000000,
                .frequency_stepsize     = 166667,
@@ -346,38 +345,36 @@ int as102_dvb_register_fe(struct as102_dev_t *as102_dev,
        return errno;
 }
 
-static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps,
                                         struct as10x_tps *as10x_tps)
 {
 
-       struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm;
-
        /* extract consteallation */
-       switch (as10x_tps->constellation) {
+       switch (as10x_tps->modulation) {
        case CONST_QPSK:
-               fe_tps->constellation = QPSK;
+               fe_tps->modulation = QPSK;
                break;
        case CONST_QAM16:
-               fe_tps->constellation = QAM_16;
+               fe_tps->modulation = QAM_16;
                break;
        case CONST_QAM64:
-               fe_tps->constellation = QAM_64;
+               fe_tps->modulation = QAM_64;
                break;
        }
 
        /* extract hierarchy */
        switch (as10x_tps->hierarchy) {
        case HIER_NONE:
-               fe_tps->hierarchy_information = HIERARCHY_NONE;
+               fe_tps->hierarchy = HIERARCHY_NONE;
                break;
        case HIER_ALPHA_1:
-               fe_tps->hierarchy_information = HIERARCHY_1;
+               fe_tps->hierarchy = HIERARCHY_1;
                break;
        case HIER_ALPHA_2:
-               fe_tps->hierarchy_information = HIERARCHY_2;
+               fe_tps->hierarchy = HIERARCHY_2;
                break;
        case HIER_ALPHA_4:
-               fe_tps->hierarchy_information = HIERARCHY_4;
+               fe_tps->hierarchy = HIERARCHY_4;
                break;
        }
 
@@ -475,7 +472,7 @@ static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
 }
 
 static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
-                         struct dvb_frontend_parameters *params)
+                         struct dtv_frontend_properties *params)
 {
 
        /* set frequency */
@@ -484,21 +481,21 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
        /* fix interleaving_mode */
        tune_args->interleaving_mode = INTLV_NATIVE;
 
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_8_MHZ:
+       switch (params->bandwidth_hz) {
+       case 8000000:
                tune_args->bandwidth = BW_8_MHZ;
                break;
-       case BANDWIDTH_7_MHZ:
+       case 7000000:
                tune_args->bandwidth = BW_7_MHZ;
                break;
-       case BANDWIDTH_6_MHZ:
+       case 6000000:
                tune_args->bandwidth = BW_6_MHZ;
                break;
        default:
                tune_args->bandwidth = BW_8_MHZ;
        }
 
-       switch (params->u.ofdm.guard_interval) {
+       switch (params->guard_interval) {
        case GUARD_INTERVAL_1_32:
                tune_args->guard_interval = GUARD_INT_1_32;
                break;
@@ -517,22 +514,22 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
                break;
        }
 
-       switch (params->u.ofdm.constellation) {
+       switch (params->modulation) {
        case QPSK:
-               tune_args->constellation = CONST_QPSK;
+               tune_args->modulation = CONST_QPSK;
                break;
        case QAM_16:
-               tune_args->constellation = CONST_QAM16;
+               tune_args->modulation = CONST_QAM16;
                break;
        case QAM_64:
-               tune_args->constellation = CONST_QAM64;
+               tune_args->modulation = CONST_QAM64;
                break;
        default:
-               tune_args->constellation = CONST_UNKNOWN;
+               tune_args->modulation = CONST_UNKNOWN;
                break;
        }
 
-       switch (params->u.ofdm.transmission_mode) {
+       switch (params->transmission_mode) {
        case TRANSMISSION_MODE_2K:
                tune_args->transmission_mode = TRANS_MODE_2K;
                break;
@@ -543,7 +540,7 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
                tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
        }
 
-       switch (params->u.ofdm.hierarchy_information) {
+       switch (params->hierarchy) {
        case HIERARCHY_NONE:
                tune_args->hierarchy = HIER_NONE;
                break;
@@ -571,19 +568,19 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
         * if HP/LP are both set to FEC_NONE, HP will be selected.
         */
        if ((tune_args->hierarchy != HIER_NONE) &&
-                      ((params->u.ofdm.code_rate_LP == FEC_NONE) ||
-                       (params->u.ofdm.code_rate_HP == FEC_NONE))) {
+                      ((params->code_rate_LP == FEC_NONE) ||
+                       (params->code_rate_HP == FEC_NONE))) {
 
-               if (params->u.ofdm.code_rate_LP == FEC_NONE) {
+               if (params->code_rate_LP == FEC_NONE) {
                        tune_args->hier_select = HIER_HIGH_PRIORITY;
                        tune_args->code_rate =
-                          as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+                          as102_fe_get_code_rate(params->code_rate_HP);
                }
 
-               if (params->u.ofdm.code_rate_HP == FEC_NONE) {
+               if (params->code_rate_HP == FEC_NONE) {
                        tune_args->hier_select = HIER_LOW_PRIORITY;
                        tune_args->code_rate =
-                          as102_fe_get_code_rate(params->u.ofdm.code_rate_LP);
+                          as102_fe_get_code_rate(params->code_rate_LP);
                }
 
                dprintk(debug, "\thierarchy: 0x%02x  "
@@ -596,8 +593,6 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
                        tune_args->code_rate);
        } else {
                tune_args->code_rate =
-                       as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+                       as102_fe_get_code_rate(params->code_rate_HP);
        }
 }
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index c019df933cc988891dc1a28f80dc53ce9794e9a7..43ebc43e6b9a1e1841fcb3dc87e4811216359311 100644 (file)
@@ -26,7 +26,6 @@
 #include "as102_drv.h"
 #include "as102_fw.h"
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
 char as102_st_fw1[] = "as102_data1_st.hex";
 char as102_st_fw2[] = "as102_data2_st.hex";
 char as102_dt_fw1[] = "as102_data1_dt.hex";
@@ -59,7 +58,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
        unsigned char *src, dst;
 
        if (*fw_data++ != ':') {
-               printk(KERN_ERR "invalid firmware file\n");
+               pr_err("invalid firmware file\n");
                return -EFAULT;
        }
 
@@ -102,7 +101,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
        return (count * 2) + 2;
 }
 
-static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap,
+static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
                                 unsigned char *cmd,
                                 const struct firmware *firmware) {
 
@@ -163,19 +162,14 @@ error:
        return (errno == 0) ? total_read_bytes : errno;
 }
 
-int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
+int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
 {
        int errno = -EFAULT;
        const struct firmware *firmware;
        unsigned char *cmd_buf = NULL;
        char *fw1, *fw2;
-
-#if defined(CONFIG_AS102_USB)
        struct usb_device *dev = bus_adap->usb_dev;
-#endif
-#if defined(CONFIG_AS102_SPI)
-       struct spi_device *dev = bus_adap->spi_dev;
-#endif
+
        ENTER();
 
        /* select fw file to upload */
@@ -187,7 +181,6 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
                fw2 = as102_st_fw2;
        }
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
        /* allocate buffer to store firmware upload command and data */
        cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
        if (cmd_buf == NULL) {
@@ -198,21 +191,21 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
        /* request kernel to locate firmware file: part1 */
        errno = request_firmware(&firmware, fw1, &dev->dev);
        if (errno < 0) {
-               printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
-                                DRIVER_NAME, fw1);
+               pr_err("%s: unable to locate firmware file: %s\n",
+                      DRIVER_NAME, fw1);
                goto error;
        }
 
        /* initiate firmware upload */
        errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
        if (errno < 0) {
-               printk(KERN_ERR "%s: error during firmware upload part1\n",
-                                DRIVER_NAME);
+               pr_err("%s: error during firmware upload part1\n",
+                      DRIVER_NAME);
                goto error;
        }
 
-       printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
-                        DRIVER_NAME, fw1);
+       pr_info("%s: firmware: %s loaded with success\n",
+               DRIVER_NAME, fw1);
        release_firmware(firmware);
 
        /* wait for boot to complete */
@@ -221,31 +214,28 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
        /* request kernel to locate firmware file: part2 */
        errno = request_firmware(&firmware, fw2, &dev->dev);
        if (errno < 0) {
-               printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
-                                DRIVER_NAME, fw2);
+               pr_err("%s: unable to locate firmware file: %s\n",
+                      DRIVER_NAME, fw2);
                goto error;
        }
 
        /* initiate firmware upload */
        errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
        if (errno < 0) {
-               printk(KERN_ERR "%s: error during firmware upload part2\n",
-                                DRIVER_NAME);
+               pr_err("%s: error during firmware upload part2\n",
+                      DRIVER_NAME);
                goto error;
        }
 
-       printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
-                       DRIVER_NAME, fw2);
+       pr_info("%s: firmware: %s loaded with success\n",
+               DRIVER_NAME, fw2);
 error:
        /* free data buffer */
        kfree(cmd_buf);
        /* release firmware if needed */
        if (firmware != NULL)
                release_firmware(firmware);
-#endif
+
        LEAVE();
        return errno;
 }
-#endif
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index 27e5347e2e19472a4c52b118f651c47db726ffd4..bd21f0554392bba3f860ce4661740c954da3bbe3 100644 (file)
 
 extern int dual_tuner;
 
-#pragma pack(1)
 struct as10x_raw_fw_pkt {
        unsigned char address[4];
        unsigned char data[MAX_FW_PKT_SIZE - 6];
-};
+} __packed;
 
 struct as10x_fw_pkt_t {
        union {
@@ -32,11 +31,8 @@ struct as10x_fw_pkt_t {
                unsigned char length[2];
        } u;
        struct as10x_raw_fw_pkt raw;
-};
-#pragma pack()
+} __packed;
 
 #ifdef __KERNEL__
-int as102_fw_upload(struct as102_bus_adapter_t *bus_adap);
+int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap);
 #endif
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index 264be2dbd2a41c98fd2d1861ede5a57716328879..d775be0173eaff3d2276bfb1f36b052843af8c87 100644 (file)
@@ -42,30 +42,32 @@ static struct usb_device_id as102_usb_id_table[] = {
        { USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) },
        { USB_DEVICE(ELGATO_EYETV_DTT_USB_VID, ELGATO_EYETV_DTT_USB_PID) },
        { USB_DEVICE(NBOX_DVBT_DONGLE_USB_VID, NBOX_DVBT_DONGLE_USB_PID) },
+       { USB_DEVICE(SKY_IT_DIGITAL_KEY_USB_VID, SKY_IT_DIGITAL_KEY_USB_PID) },
        { } /* Terminating entry */
 };
 
 /* Note that this table must always have the same number of entries as the
    as102_usb_id_table struct */
-static const char *as102_device_names[] = {
+static const char * const as102_device_names[] = {
        AS102_REFERENCE_DESIGN,
        AS102_PCTV_74E,
        AS102_ELGATO_EYETV_DTT_NAME,
        AS102_NBOX_DVBT_DONGLE_NAME,
+       AS102_SKY_IT_DIGITAL_KEY_NAME,
        NULL /* Terminating entry */
 };
 
 struct usb_driver as102_usb_driver = {
-       .name        DRIVER_FULL_NAME,
-       .probe       as102_usb_probe,
-       .disconnect  as102_usb_disconnect,
-       .id_table    as102_usb_id_table
+       .name           = DRIVER_FULL_NAME,
+       .probe          = as102_usb_probe,
+       .disconnect     = as102_usb_disconnect,
+       .id_table       = as102_usb_id_table
 };
 
 static const struct file_operations as102_dev_fops = {
-       .owner   = THIS_MODULE,
-       .open    = as102_open,
-       .release = as102_release,
+       .owner          = THIS_MODULE,
+       .open           = as102_open,
+       .release        = as102_release,
 };
 
 static struct usb_class_driver as102_usb_class_driver = {
@@ -74,7 +76,7 @@ static struct usb_class_driver as102_usb_class_driver = {
        .minor_base     = AS102_DEVICE_MAJOR,
 };
 
-static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
+static int as102_usb_xfer_cmd(struct as10x_bus_adapter_t *bus_adap,
                              unsigned char *send_buf, int send_buf_len,
                              unsigned char *recv_buf, int recv_buf_len)
 {
@@ -131,7 +133,7 @@ static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
        return ret;
 }
 
-static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
+static int as102_send_ep1(struct as10x_bus_adapter_t *bus_adap,
                          unsigned char *send_buf,
                          int send_buf_len,
                          int swap32)
@@ -154,7 +156,7 @@ static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
        return ret ? ret : actual_len;
 }
 
-static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap,
+static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap,
                   unsigned char *recv_buf, int recv_buf_len)
 {
        int ret = 0, actual_len;
@@ -337,7 +339,7 @@ static void as102_usb_disconnect(struct usb_interface *intf)
        /* decrement usage counter */
        kref_put(&as102_dev->kref, as102_usb_release);
 
-       printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME);
+       pr_info("%s: device has been disconnected\n", DRIVER_NAME);
 
        LEAVE();
 }
@@ -351,19 +353,19 @@ static int as102_usb_probe(struct usb_interface *intf,
 
        ENTER();
 
-       as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
-       if (as102_dev == NULL) {
-               err("%s: kzalloc failed", __func__);
-               return -ENOMEM;
-       }
-
        /* This should never actually happen */
        if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) !=
            (sizeof(as102_device_names) / sizeof(const char *))) {
-               printk(KERN_ERR "Device names table invalid size");
+               pr_err("Device names table invalid size");
                return -EINVAL;
        }
 
+       as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
+       if (as102_dev == NULL) {
+               err("%s: kzalloc failed", __func__);
+               return -ENOMEM;
+       }
+
        /* Assign the user-friendly device name */
        for (i = 0; i < (sizeof(as102_usb_id_table) /
                         sizeof(struct usb_device_id)); i++) {
@@ -399,7 +401,7 @@ static int as102_usb_probe(struct usb_interface *intf,
                goto failed;
        }
 
-       printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME);
+       pr_info("%s: device has been detected\n", DRIVER_NAME);
 
        /* request buffer allocation for streaming */
        ret = as102_alloc_usb_stream_buffer(as102_dev);
@@ -432,8 +434,8 @@ static int as102_open(struct inode *inode, struct file *file)
        /* fetch device from usb interface */
        intf = usb_find_interface(&as102_usb_driver, minor);
        if (intf == NULL) {
-               printk(KERN_ERR "%s: can't find device for minor %d\n",
-                               __func__, minor);
+               pr_err("%s: can't find device for minor %d\n",
+                      __func__, minor);
                ret = -ENODEV;
                goto exit;
        }
@@ -474,5 +476,3 @@ static int as102_release(struct inode *inode, struct file *file)
 }
 
 MODULE_DEVICE_TABLE(usb, as102_usb_id_table);
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index fb1fc41dcd7968f4ab9ec80998e7853a811d558f..fc2884ab02a280520aa755aa493bc3229c8aab71 100644 (file)
 #define NBOX_DVBT_DONGLE_USB_VID       0x0b89
 #define NBOX_DVBT_DONGLE_USB_PID       0x0007
 
+/* Sky Italia: Digital Key (green led) */
+#define AS102_SKY_IT_DIGITAL_KEY_NAME  "Sky IT Digital Key (green led)"
+#define SKY_IT_DIGITAL_KEY_USB_VID     0x2137
+#define SKY_IT_DIGITAL_KEY_USB_PID     0x0001
+
 void as102_urb_stream_irq(struct urb *urb);
 
 struct as10x_usb_token_cmd_t {
@@ -56,4 +61,3 @@ struct as10x_usb_token_cmd_t {
        struct as10x_cmd_t r;
 };
 #endif
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
index 0dcba806578065637532657438aeedd0a858da4c..262bb94ad27e5d422231a5074ab2c94f57d30663 100644 (file)
 
 /**
  * as10x_cmd_turn_on - send turn on command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:   pointer to AS10x bus adapter
  *
  * Return 0 when no error, < 0 in case of error.
  */
-int as10x_cmd_turn_on(as10x_handle_t *phandle)
+int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
 {
        int error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.turn_on.req));
 
        /* fill command */
        pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
-                                              sizeof(pcmd->body.turn_on.req) +
-                                              HEADER_SIZE,
-                                              (uint8_t *) prsp,
-                                              sizeof(prsp->body.turn_on.rsp) +
-                                              HEADER_SIZE);
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
+                                           sizeof(pcmd->body.turn_on.req) +
+                                           HEADER_SIZE,
+                                           (uint8_t *) prsp,
+                                           sizeof(prsp->body.turn_on.rsp) +
+                                           HEADER_SIZE);
        } else {
                error = AS10X_CMD_ERROR;
        }
@@ -71,31 +71,31 @@ out:
 
 /**
  * as10x_cmd_turn_off - send turn off command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:   pointer to AS10x bus adapter
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_turn_off(as10x_handle_t *phandle)
+int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
 {
        int error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.turn_off.req));
 
        /* fill command */
        pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(
-                       phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(
+                       adap, (uint8_t *) pcmd,
                        sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
                        (uint8_t *) prsp,
                        sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
@@ -116,23 +116,24 @@ out:
 
 /**
  * as10x_cmd_set_tune - send set tune command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap:    pointer to AS10x bus adapter
  * @ptune:   tune parameters
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
+int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
+                      struct as10x_tune_args *ptune)
 {
        int error;
        struct as10x_cmd_t *preq, *prsp;
 
        ENTER();
 
-       preq = phandle->cmd;
-       prsp = phandle->rsp;
+       preq = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(preq, (++phandle->cmd_xid),
+       as10x_cmd_build(preq, (++adap->cmd_xid),
                        sizeof(preq->body.set_tune.req));
 
        /* fill command */
@@ -140,7 +141,7 @@ int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
        preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
        preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
        preq->body.set_tune.req.args.hier_select = ptune->hier_select;
-       preq->body.set_tune.req.args.constellation = ptune->constellation;
+       preq->body.set_tune.req.args.modulation = ptune->modulation;
        preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
        preq->body.set_tune.req.args.interleaving_mode  =
                ptune->interleaving_mode;
@@ -150,14 +151,14 @@ int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
                ptune->transmission_mode;
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle,
-                                              (uint8_t *) preq,
-                                              sizeof(preq->body.set_tune.req)
-                                              + HEADER_SIZE,
-                                              (uint8_t *) prsp,
-                                              sizeof(prsp->body.set_tune.rsp)
-                                              + HEADER_SIZE);
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap,
+                                           (uint8_t *) preq,
+                                           sizeof(preq->body.set_tune.req)
+                                           + HEADER_SIZE,
+                                           (uint8_t *) prsp,
+                                           sizeof(prsp->body.set_tune.rsp)
+                                           + HEADER_SIZE);
        } else {
                error = AS10X_CMD_ERROR;
        }
@@ -175,12 +176,12 @@ out:
 
 /**
  * as10x_cmd_get_tune_status - send get tune status command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
  * @pstatus: pointer to updated status structure of the current tune
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
                              struct as10x_tune_status *pstatus)
 {
        int error;
@@ -188,11 +189,11 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
 
        ENTER();
 
-       preq = phandle->cmd;
-       prsp = phandle->rsp;
+       preq = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(preq, (++phandle->cmd_xid),
+       as10x_cmd_build(preq, (++adap->cmd_xid),
                        sizeof(preq->body.get_tune_status.req));
 
        /* fill command */
@@ -200,9 +201,9 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
                cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(
-                       phandle,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(
+                       adap,
                        (uint8_t *) preq,
                        sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
                        (uint8_t *) prsp,
@@ -232,24 +233,24 @@ out:
 }
 
 /**
- * send get TPS command to AS10x
- * @phandle:   pointer to AS10x handle
+ * as10x_cmd_get_tps - send get TPS command to AS10x
+ * @adap:      pointer to AS10x handle
  * @ptps:      pointer to TPS parameters structure
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
+int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
 {
        int error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.get_tps.req));
 
        /* fill command */
@@ -257,14 +258,14 @@ int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
                cpu_to_le16(CONTROL_PROC_GETTPS);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle,
-                                              (uint8_t *) pcmd,
-                                              sizeof(pcmd->body.get_tps.req) +
-                                              HEADER_SIZE,
-                                              (uint8_t *) prsp,
-                                              sizeof(prsp->body.get_tps.rsp) +
-                                              HEADER_SIZE);
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap,
+                                           (uint8_t *) pcmd,
+                                           sizeof(pcmd->body.get_tps.req) +
+                                           HEADER_SIZE,
+                                           (uint8_t *) prsp,
+                                           sizeof(prsp->body.get_tps.rsp) +
+                                           HEADER_SIZE);
        } else {
                error = AS10X_CMD_ERROR;
        }
@@ -278,7 +279,7 @@ int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
                goto out;
 
        /* Response OK -> get response data */
-       ptps->constellation = prsp->body.get_tps.rsp.tps.constellation;
+       ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
        ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
        ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
        ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
@@ -296,12 +297,12 @@ out:
 
 /**
  * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
- * @phandle:       pointer to AS10x handle
+ * @adap:          pointer to AS10x bus adapter
  * @pdemod_stats:  pointer to demod stats parameters structure
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
+int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
                              struct as10x_demod_stats *pdemod_stats)
 {
        int error;
@@ -309,11 +310,11 @@ int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.get_demod_stats.req));
 
        /* fill command */
@@ -321,8 +322,8 @@ int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
                cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap,
                                (uint8_t *) pcmd,
                                sizeof(pcmd->body.get_demod_stats.req)
                                + HEADER_SIZE,
@@ -360,13 +361,13 @@ out:
 
 /**
  * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
- * @phandle:  pointer to AS10x handle
+ * @adap:     pointer to AS10x bus adapter
  * @is_ready: pointer to value indicating when impulse
  *           response data is ready
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_get_impulse_resp(as10x_handle_t     *phandle,
+int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
                               uint8_t *is_ready)
 {
        int error;
@@ -374,11 +375,11 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t     *phandle,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.get_impulse_rsp.req));
 
        /* fill command */
@@ -386,8 +387,8 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t     *phandle,
                cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap,
                                        (uint8_t *) pcmd,
                                        sizeof(pcmd->body.get_impulse_rsp.req)
                                        + HEADER_SIZE,
index 01a716380e0a702350770ceea2121bdc9211a4e7..4ea249e7adab947c27488f9c57427d04a504ab0b 100644 (file)
 /*********************************/
 /*       MACRO DEFINITIONS       */
 /*********************************/
-#define AS10X_CMD_ERROR -1
+#define AS10X_CMD_ERROR                -1
 
-#define SERVICE_PROG_ID        0x0002
-#define SERVICE_PROG_VERSION   0x0001
+#define SERVICE_PROG_ID                0x0002
+#define SERVICE_PROG_VERSION   0x0001
 
-#define HIER_NONE              0x00
-#define HIER_LOW_PRIORITY      0x01
+#define HIER_NONE              0x00
+#define HIER_LOW_PRIORITY      0x01
 
 #define HEADER_SIZE (sizeof(struct as10x_cmd_header_t))
 
 /* context request types */
-#define GET_CONTEXT_DATA        1
-#define SET_CONTEXT_DATA        2
+#define GET_CONTEXT_DATA       1
+#define SET_CONTEXT_DATA       2
 
 /* ODSP suspend modes */
-#define CFG_MODE_ODSP_RESUME  0
-#define CFG_MODE_ODSP_SUSPEND 1
+#define CFG_MODE_ODSP_RESUME   0
+#define CFG_MODE_ODSP_SUSPEND  1
 
 /* Dump memory size */
-#define DUMP_BLOCK_SIZE_MAX   0x20
+#define DUMP_BLOCK_SIZE_MAX    0x20
 
 /*********************************/
 /*     TYPE DEFINITION           */
 /*********************************/
-typedef enum {
-   CONTROL_PROC_TURNON               = 0x0001,
-   CONTROL_PROC_TURNON_RSP           = 0x0100,
-   CONTROL_PROC_SET_REGISTER         = 0x0002,
-   CONTROL_PROC_SET_REGISTER_RSP     = 0x0200,
-   CONTROL_PROC_GET_REGISTER         = 0x0003,
-   CONTROL_PROC_GET_REGISTER_RSP     = 0x0300,
-   CONTROL_PROC_SETTUNE              = 0x000A,
-   CONTROL_PROC_SETTUNE_RSP          = 0x0A00,
-   CONTROL_PROC_GETTUNESTAT          = 0x000B,
-   CONTROL_PROC_GETTUNESTAT_RSP      = 0x0B00,
-   CONTROL_PROC_GETTPS               = 0x000D,
-   CONTROL_PROC_GETTPS_RSP           = 0x0D00,
-   CONTROL_PROC_SETFILTER            = 0x000E,
-   CONTROL_PROC_SETFILTER_RSP        = 0x0E00,
-   CONTROL_PROC_REMOVEFILTER         = 0x000F,
-   CONTROL_PROC_REMOVEFILTER_RSP     = 0x0F00,
-   CONTROL_PROC_GET_IMPULSE_RESP     = 0x0012,
-   CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200,
-   CONTROL_PROC_START_STREAMING      = 0x0013,
-   CONTROL_PROC_START_STREAMING_RSP  = 0x1300,
-   CONTROL_PROC_STOP_STREAMING       = 0x0014,
-   CONTROL_PROC_STOP_STREAMING_RSP   = 0x1400,
-   CONTROL_PROC_GET_DEMOD_STATS      = 0x0015,
-   CONTROL_PROC_GET_DEMOD_STATS_RSP  = 0x1500,
-   CONTROL_PROC_ELNA_CHANGE_MODE     = 0x0016,
-   CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600,
-   CONTROL_PROC_ODSP_CHANGE_MODE     = 0x0017,
-   CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700,
-   CONTROL_PROC_AGC_CHANGE_MODE      = 0x0018,
-   CONTROL_PROC_AGC_CHANGE_MODE_RSP  = 0x1800,
-
-   CONTROL_PROC_CONTEXT              = 0x00FC,
-   CONTROL_PROC_CONTEXT_RSP          = 0xFC00,
-   CONTROL_PROC_DUMP_MEMORY          = 0x00FD,
-   CONTROL_PROC_DUMP_MEMORY_RSP      = 0xFD00,
-   CONTROL_PROC_DUMPLOG_MEMORY       = 0x00FE,
-   CONTROL_PROC_DUMPLOG_MEMORY_RSP   = 0xFE00,
-   CONTROL_PROC_TURNOFF              = 0x00FF,
-   CONTROL_PROC_TURNOFF_RSP          = 0xFF00
-} control_proc;
-
-
-#pragma pack(1)
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-   } rsp;
-} TURN_ON;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t err;
-   } rsp;
-} TURN_OFF;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* tune params */
-      struct as10x_tune_args args;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-   } rsp;
-} SET_TUNE;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-      /* tune status */
-      struct as10x_tune_status sts;
-   } rsp;
-} GET_TUNE_STATUS;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-      /* tps details */
-      struct as10x_tps tps;
-   } rsp;
-} GET_TPS;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t  proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-   } rsp;
-} COMMON;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t  proc_id;
-      /* PID to filter */
-      uint16_t  pid;
-      /* stream type (MPE, PSI/SI or PES )*/
-      uint8_t stream_type;
-      /* PID index in filter table */
-      uint8_t idx;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-      /* Filter id */
-      uint8_t filter_id;
-   } rsp;
-} ADD_PID_FILTER;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t  proc_id;
-      /* PID to remove */
-      uint16_t  pid;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* response error */
-      uint8_t error;
-   } rsp;
-} DEL_PID_FILTER;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-   } rsp;
-} START_STREAMING;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-   } rsp;
-} STOP_STREAMING;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-      /* demod stats */
-      struct as10x_demod_stats stats;
-   } rsp;
-} GET_DEMOD_STATS;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-      /* impulse response ready */
-      uint8_t is_ready;
-   } rsp;
-} GET_IMPULSE_RESP;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* value to write (for set context)*/
-      struct as10x_register_value reg_val;
-      /* context tag */
-      uint16_t tag;
-      /* context request type */
-      uint16_t type;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* value read (for get context) */
-      struct as10x_register_value reg_val;
-      /* context request type */
-      uint16_t type;
-      /* error */
-      uint8_t error;
-   } rsp;
-} FW_CONTEXT;
-
-typedef union {
-   /* request */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* register description */
-      struct as10x_register_addr reg_addr;
-      /* register content */
-      struct as10x_register_value reg_val;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-   } rsp;
-} SET_REGISTER;
-
-typedef union {
-   /* request */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* register description */
-      struct as10x_register_addr reg_addr;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-      /* register content */
-      struct as10x_register_value reg_val;
-   } rsp;
-} GET_REGISTER;
-
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* mode */
-      uint8_t mode;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-   } rsp;
-} CFG_CHANGE_MODE;
+enum control_proc {
+       CONTROL_PROC_TURNON                     = 0x0001,
+       CONTROL_PROC_TURNON_RSP                 = 0x0100,
+       CONTROL_PROC_SET_REGISTER               = 0x0002,
+       CONTROL_PROC_SET_REGISTER_RSP           = 0x0200,
+       CONTROL_PROC_GET_REGISTER               = 0x0003,
+       CONTROL_PROC_GET_REGISTER_RSP           = 0x0300,
+       CONTROL_PROC_SETTUNE                    = 0x000A,
+       CONTROL_PROC_SETTUNE_RSP                = 0x0A00,
+       CONTROL_PROC_GETTUNESTAT                = 0x000B,
+       CONTROL_PROC_GETTUNESTAT_RSP            = 0x0B00,
+       CONTROL_PROC_GETTPS                     = 0x000D,
+       CONTROL_PROC_GETTPS_RSP                 = 0x0D00,
+       CONTROL_PROC_SETFILTER                  = 0x000E,
+       CONTROL_PROC_SETFILTER_RSP              = 0x0E00,
+       CONTROL_PROC_REMOVEFILTER               = 0x000F,
+       CONTROL_PROC_REMOVEFILTER_RSP           = 0x0F00,
+       CONTROL_PROC_GET_IMPULSE_RESP           = 0x0012,
+       CONTROL_PROC_GET_IMPULSE_RESP_RSP       = 0x1200,
+       CONTROL_PROC_START_STREAMING            = 0x0013,
+       CONTROL_PROC_START_STREAMING_RSP        = 0x1300,
+       CONTROL_PROC_STOP_STREAMING             = 0x0014,
+       CONTROL_PROC_STOP_STREAMING_RSP         = 0x1400,
+       CONTROL_PROC_GET_DEMOD_STATS            = 0x0015,
+       CONTROL_PROC_GET_DEMOD_STATS_RSP        = 0x1500,
+       CONTROL_PROC_ELNA_CHANGE_MODE           = 0x0016,
+       CONTROL_PROC_ELNA_CHANGE_MODE_RSP       = 0x1600,
+       CONTROL_PROC_ODSP_CHANGE_MODE           = 0x0017,
+       CONTROL_PROC_ODSP_CHANGE_MODE_RSP       = 0x1700,
+       CONTROL_PROC_AGC_CHANGE_MODE            = 0x0018,
+       CONTROL_PROC_AGC_CHANGE_MODE_RSP        = 0x1800,
+
+       CONTROL_PROC_CONTEXT                    = 0x00FC,
+       CONTROL_PROC_CONTEXT_RSP                = 0xFC00,
+       CONTROL_PROC_DUMP_MEMORY                = 0x00FD,
+       CONTROL_PROC_DUMP_MEMORY_RSP            = 0xFD00,
+       CONTROL_PROC_DUMPLOG_MEMORY             = 0x00FE,
+       CONTROL_PROC_DUMPLOG_MEMORY_RSP         = 0xFE00,
+       CONTROL_PROC_TURNOFF                    = 0x00FF,
+       CONTROL_PROC_TURNOFF_RSP                = 0xFF00
+};
+
+union as10x_turn_on {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_turn_off {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t err;
+       } rsp;
+} __packed;
+
+union as10x_set_tune {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* tune params */
+               struct as10x_tune_args args;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_get_tune_status {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+               /* tune status */
+               struct as10x_tune_status sts;
+       } rsp;
+} __packed;
+
+union as10x_get_tps {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+               /* tps details */
+               struct as10x_tps tps;
+       } rsp;
+} __packed;
+
+union as10x_common {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t  proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_add_pid_filter {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t  proc_id;
+               /* PID to filter */
+               uint16_t  pid;
+               /* stream type (MPE, PSI/SI or PES )*/
+               uint8_t stream_type;
+               /* PID index in filter table */
+               uint8_t idx;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+               /* Filter id */
+               uint8_t filter_id;
+       } rsp;
+} __packed;
+
+union as10x_del_pid_filter {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t  proc_id;
+               /* PID to remove */
+               uint16_t  pid;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* response error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_start_streaming {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_stop_streaming {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_get_demod_stats {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+               /* demod stats */
+               struct as10x_demod_stats stats;
+       } rsp;
+} __packed;
+
+union as10x_get_impulse_resp {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+               /* impulse response ready */
+               uint8_t is_ready;
+       } rsp;
+} __packed;
+
+union as10x_fw_context {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* value to write (for set context)*/
+               struct as10x_register_value reg_val;
+               /* context tag */
+               uint16_t tag;
+               /* context request type */
+               uint16_t type;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* value read (for get context) */
+               struct as10x_register_value reg_val;
+               /* context request type */
+               uint16_t type;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_set_register {
+       /* request */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* register description */
+               struct as10x_register_addr reg_addr;
+               /* register content */
+               struct as10x_register_value reg_val;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
+
+union as10x_get_register {
+       /* request */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* register description */
+               struct as10x_register_addr reg_addr;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+               /* register content */
+               struct as10x_register_value reg_val;
+       } rsp;
+} __packed;
+
+union as10x_cfg_change_mode {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* mode */
+               uint8_t mode;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+       } rsp;
+} __packed;
 
 struct as10x_cmd_header_t {
-   uint16_t req_id;
-   uint16_t prog;
-   uint16_t version;
-   uint16_t data_len;
-};
+       uint16_t req_id;
+       uint16_t prog;
+       uint16_t version;
+       uint16_t data_len;
+} __packed;
 
 #define DUMP_BLOCK_SIZE 16
-typedef union {
-   /* request */
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* dump memory type request */
-      uint8_t dump_req;
-      /* register description */
-      struct as10x_register_addr reg_addr;
-      /* nb blocks to read */
-      uint16_t num_blocks;
-   } req;
-   /* response */
-   struct {
-      /* response identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-      /* dump response */
-      uint8_t dump_rsp;
-      /* data */
-      union {
-        uint8_t  data8[DUMP_BLOCK_SIZE];
-        uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
-        uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
-      } u;
-   } rsp;
-} DUMP_MEMORY;
-
-typedef union {
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* dump memory type request */
-      uint8_t dump_req;
-   } req;
-   struct {
-      /* request identifier */
-      uint16_t proc_id;
-      /* error */
-      uint8_t error;
-      /* dump response */
-      uint8_t dump_rsp;
-      /* dump data */
-      uint8_t data[DUMP_BLOCK_SIZE];
-   } rsp;
-} DUMPLOG_MEMORY;
-
-typedef union {
-   /* request */
-   struct {
-      uint16_t proc_id;
-      uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */];
-   } req;
-   /* response */
-   struct {
-      uint16_t proc_id;
-      uint8_t error;
-      uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */
-                     - 2 /* proc_id */ - 1 /* rc */];
-   } rsp;
-} RAW_DATA;
+
+union as10x_dump_memory {
+       /* request */
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* dump memory type request */
+               uint8_t dump_req;
+               /* register description */
+               struct as10x_register_addr reg_addr;
+               /* nb blocks to read */
+               uint16_t num_blocks;
+       } req;
+       /* response */
+       struct {
+               /* response identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+               /* dump response */
+               uint8_t dump_rsp;
+               /* data */
+               union {
+                       uint8_t  data8[DUMP_BLOCK_SIZE];
+                       uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
+                       uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
+               } u;
+       } rsp;
+} __packed;
+
+union as10x_dumplog_memory {
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* dump memory type request */
+               uint8_t dump_req;
+       } req;
+       struct {
+               /* request identifier */
+               uint16_t proc_id;
+               /* error */
+               uint8_t error;
+               /* dump response */
+               uint8_t dump_rsp;
+               /* dump data */
+               uint8_t data[DUMP_BLOCK_SIZE];
+       } rsp;
+} __packed;
+
+union as10x_raw_data {
+       /* request */
+       struct {
+               uint16_t proc_id;
+               uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
+                            - 2 /* proc_id */];
+       } req;
+       /* response */
+       struct {
+               uint16_t proc_id;
+               uint8_t error;
+               uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
+                            - 2 /* proc_id */ - 1 /* rc */];
+       } rsp;
+} __packed;
 
 struct as10x_cmd_t {
-   /* header */
-   struct as10x_cmd_header_t header;
-   /* body */
-   union {
-      TURN_ON           turn_on;
-      TURN_OFF          turn_off;
-      SET_TUNE          set_tune;
-      GET_TUNE_STATUS   get_tune_status;
-      GET_TPS           get_tps;
-      COMMON            common;
-      ADD_PID_FILTER    add_pid_filter;
-      DEL_PID_FILTER    del_pid_filter;
-      START_STREAMING   start_streaming;
-      STOP_STREAMING    stop_streaming;
-      GET_DEMOD_STATS   get_demod_stats;
-      GET_IMPULSE_RESP  get_impulse_rsp;
-      FW_CONTEXT        context;
-      SET_REGISTER      set_register;
-      GET_REGISTER      get_register;
-      CFG_CHANGE_MODE   cfg_change_mode;
-      DUMP_MEMORY       dump_memory;
-      DUMPLOG_MEMORY    dumplog_memory;
-      RAW_DATA          raw_data;
-   } body;
-};
+       struct as10x_cmd_header_t header;
+       union {
+               union as10x_turn_on             turn_on;
+               union as10x_turn_off            turn_off;
+               union as10x_set_tune            set_tune;
+               union as10x_get_tune_status     get_tune_status;
+               union as10x_get_tps             get_tps;
+               union as10x_common              common;
+               union as10x_add_pid_filter      add_pid_filter;
+               union as10x_del_pid_filter      del_pid_filter;
+               union as10x_start_streaming     start_streaming;
+               union as10x_stop_streaming      stop_streaming;
+               union as10x_get_demod_stats     get_demod_stats;
+               union as10x_get_impulse_resp    get_impulse_rsp;
+               union as10x_fw_context          context;
+               union as10x_set_register        set_register;
+               union as10x_get_register        get_register;
+               union as10x_cfg_change_mode     cfg_change_mode;
+               union as10x_dump_memory         dump_memory;
+               union as10x_dumplog_memory      dumplog_memory;
+               union as10x_raw_data            raw_data;
+       } body;
+} __packed;
 
 struct as10x_token_cmd_t {
-   /* token cmd */
-   struct as10x_cmd_t c;
-   /* token response */
-   struct as10x_cmd_t r;
-};
-#pragma pack()
+       /* token cmd */
+       struct as10x_cmd_t c;
+       /* token response */
+       struct as10x_cmd_t r;
+} __packed;
 
 
 /**************************/
@@ -491,50 +488,42 @@ void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id,
                      uint16_t cmd_len);
 int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id);
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* as10x cmd */
-int as10x_cmd_turn_on(as10x_handle_t *phandle);
-int as10x_cmd_turn_off(as10x_handle_t *phandle);
+int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap);
+int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap);
 
-int as10x_cmd_set_tune(as10x_handle_t *phandle,
+int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
                       struct as10x_tune_args *ptune);
 
-int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
                              struct as10x_tune_status *pstatus);
 
-int as10x_cmd_get_tps(as10x_handle_t *phandle,
+int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap,
                      struct as10x_tps *ptps);
 
-int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
+int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t  *adap,
                              struct as10x_demod_stats *pdemod_stats);
 
-int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
+int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
                               uint8_t *is_ready);
 
 /* as10x cmd stream */
-int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap,
                             struct as10x_ts_filter *filter);
-int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap,
                             uint16_t pid_value);
 
-int as10x_cmd_start_streaming(as10x_handle_t *phandle);
-int as10x_cmd_stop_streaming(as10x_handle_t *phandle);
+int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap);
+int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap);
 
 /* as10x cmd cfg */
-int as10x_cmd_set_context(as10x_handle_t *phandle,
+int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap,
                          uint16_t tag,
                          uint32_t value);
-int as10x_cmd_get_context(as10x_handle_t *phandle,
+int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap,
                          uint16_t tag,
                          uint32_t *pvalue);
 
-int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode);
+int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode);
 int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id);
-#ifdef __cplusplus
-}
-#endif
 #endif
-/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */
index ec6f69fcf399593e219f5f2770ea1281fdde2a64..d2a4bce896231f13985fcde28e8b1e8fcec26eca 100644 (file)
 
 /**
  * as10x_cmd_get_context - Send get context command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:      pointer to AS10x bus adapter
  * @tag:       context tag
  * @pvalue:    pointer where to store context value read
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
+int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
                          uint32_t *pvalue)
 {
        int  error;
@@ -42,11 +42,11 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.context.req));
 
        /* fill command */
@@ -55,14 +55,14 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
        pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error  = phandle->ops->xfer_cmd(phandle,
-                                               (uint8_t *) pcmd,
-                                               sizeof(pcmd->body.context.req)
-                                               + HEADER_SIZE,
-                                               (uint8_t *) prsp,
-                                               sizeof(prsp->body.context.rsp)
-                                               + HEADER_SIZE);
+       if (adap->ops->xfer_cmd) {
+               error  = adap->ops->xfer_cmd(adap,
+                                            (uint8_t *) pcmd,
+                                            sizeof(pcmd->body.context.req)
+                                            + HEADER_SIZE,
+                                            (uint8_t *) prsp,
+                                            sizeof(prsp->body.context.rsp)
+                                            + HEADER_SIZE);
        } else {
                error = AS10X_CMD_ERROR;
        }
@@ -87,13 +87,13 @@ out:
 
 /**
  * as10x_cmd_set_context - send set context command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:      pointer to AS10x bus adapter
  * @tag:       context tag
  * @value:     value to set in context
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
+int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
                          uint32_t value)
 {
        int error;
@@ -101,11 +101,11 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.context.req));
 
        /* fill command */
@@ -116,14 +116,14 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
        pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error  = phandle->ops->xfer_cmd(phandle,
-                                               (uint8_t *) pcmd,
-                                               sizeof(pcmd->body.context.req)
-                                               + HEADER_SIZE,
-                                               (uint8_t *) prsp,
-                                               sizeof(prsp->body.context.rsp)
-                                               + HEADER_SIZE);
+       if (adap->ops->xfer_cmd) {
+               error  = adap->ops->xfer_cmd(adap,
+                                            (uint8_t *) pcmd,
+                                            sizeof(pcmd->body.context.req)
+                                            + HEADER_SIZE,
+                                            (uint8_t *) prsp,
+                                            sizeof(prsp->body.context.rsp)
+                                            + HEADER_SIZE);
        } else {
                error = AS10X_CMD_ERROR;
        }
@@ -142,7 +142,7 @@ out:
 
 /**
  * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:      pointer to AS10x bus adapter
  * @mode:      mode selected:
  *             - ON    : 0x0 => eLNA always ON
  *             - OFF   : 0x1 => eLNA always OFF
@@ -151,18 +151,18 @@ out:
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
+int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode)
 {
        int error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.cfg_change_mode.req));
 
        /* fill command */
@@ -171,8 +171,8 @@ int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
        pcmd->body.cfg_change_mode.req.mode = mode;
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error  = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error  = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
                                sizeof(pcmd->body.cfg_change_mode.req)
                                + HEADER_SIZE, (uint8_t *) prsp,
                                sizeof(prsp->body.cfg_change_mode.rsp)
index 045c706831935f87b8c3a6ec3d6fdf338187bf50..6d000f60fb0e9650fe10d0aefc7cd986dfe38b73 100644 (file)
 
 /**
  * as10x_cmd_add_PID_filter - send add filter command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:      pointer to AS10x bus adapter
  * @filter:    TSFilter filter for DVB-T
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap,
                             struct as10x_ts_filter *filter)
 {
        int error;
@@ -36,11 +36,11 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.add_pid_filter.req));
 
        /* fill command */
@@ -55,8 +55,8 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
                pcmd->body.add_pid_filter.req.idx = 0xFF;
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
                                sizeof(pcmd->body.add_pid_filter.req)
                                + HEADER_SIZE, (uint8_t *) prsp,
                                sizeof(prsp->body.add_pid_filter.rsp)
@@ -83,12 +83,12 @@ out:
 
 /**
  * as10x_cmd_del_PID_filter - Send delete filter command to AS10x
- * @phandle:      pointer to AS10x handle
+ * @adap:         pointer to AS10x bus adapte
  * @pid_value:    PID to delete
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap,
                             uint16_t pid_value)
 {
        int error;
@@ -96,11 +96,11 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.del_pid_filter.req));
 
        /* fill command */
@@ -109,8 +109,8 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
        pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
                                sizeof(pcmd->body.del_pid_filter.req)
                                + HEADER_SIZE, (uint8_t *) prsp,
                                sizeof(prsp->body.del_pid_filter.rsp)
@@ -132,22 +132,22 @@ out:
 
 /**
  * as10x_cmd_start_streaming - Send start streaming command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:   pointer to AS10x bus adapter
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_start_streaming(as10x_handle_t *phandle)
+int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap)
 {
        int error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.start_streaming.req));
 
        /* fill command */
@@ -155,8 +155,8 @@ int as10x_cmd_start_streaming(as10x_handle_t *phandle)
                cpu_to_le16(CONTROL_PROC_START_STREAMING);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
                                sizeof(pcmd->body.start_streaming.req)
                                + HEADER_SIZE, (uint8_t *) prsp,
                                sizeof(prsp->body.start_streaming.rsp)
@@ -178,22 +178,22 @@ out:
 
 /**
  * as10x_cmd_stop_streaming - Send stop streaming command to AS10x
- * @phandle:   pointer to AS10x handle
+ * @adap:   pointer to AS10x bus adapter
  *
  * Return 0 on success or negative value in case of error.
  */
-int as10x_cmd_stop_streaming(as10x_handle_t *phandle)
+int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap)
 {
        int8_t error;
        struct as10x_cmd_t *pcmd, *prsp;
 
        ENTER();
 
-       pcmd = phandle->cmd;
-       prsp = phandle->rsp;
+       pcmd = adap->cmd;
+       prsp = adap->rsp;
 
        /* prepare command */
-       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+       as10x_cmd_build(pcmd, (++adap->cmd_xid),
                        sizeof(pcmd->body.stop_streaming.req));
 
        /* fill command */
@@ -201,8 +201,8 @@ int as10x_cmd_stop_streaming(as10x_handle_t *phandle)
                cpu_to_le16(CONTROL_PROC_STOP_STREAMING);
 
        /* send command */
-       if (phandle->ops->xfer_cmd) {
-               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+       if (adap->ops->xfer_cmd) {
+               error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
                                sizeof(pcmd->body.stop_streaming.req)
                                + HEADER_SIZE, (uint8_t *) prsp,
                                sizeof(prsp->body.stop_streaming.rsp)
index 4f01a76e98291cb26d72f91244f96c57a83f4df5..62b9795ee424de77a142f284ef3f26860afa043d 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #ifdef __KERNEL__
-struct as102_bus_adapter_t;
+struct as10x_bus_adapter_t;
 struct as102_dev_t;
 
-#define as10x_handle_t struct as102_bus_adapter_t
 #include "as10x_cmd.h"
 
 /* values for "mode" field */
-#define REGMODE8         8
-#define REGMODE16        16
-#define REGMODE32        32
+#define REGMODE8       8
+#define REGMODE16      16
+#define REGMODE32      32
 
 struct as102_priv_ops_t {
-       int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap,
+       int (*upload_fw_pkt) (struct as10x_bus_adapter_t *bus_adap,
                              unsigned char *buf, int buflen, int swap32);
 
-       int (*send_cmd) (struct as102_bus_adapter_t *bus_adap,
+       int (*send_cmd) (struct as10x_bus_adapter_t *bus_adap,
                         unsigned char *buf, int buflen);
 
-       int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap,
+       int (*xfer_cmd) (struct as10x_bus_adapter_t *bus_adap,
                         unsigned char *send_buf, int send_buf_len,
                         unsigned char *recv_buf, int recv_buf_len);
-/*
-       int (*pid_filter) (struct as102_bus_adapter_t *bus_adap,
-                          int index, u16 pid, int onoff);
-*/
+
        int (*start_stream) (struct as102_dev_t *dev);
        void (*stop_stream) (struct as102_dev_t *dev);
 
-       int (*reset_target) (struct as102_bus_adapter_t *bus_adap);
+       int (*reset_target) (struct as10x_bus_adapter_t *bus_adap);
 
-       int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode,
+       int (*read_write)(struct as10x_bus_adapter_t *bus_adap, uint8_t mode,
                          uint32_t rd_addr, uint16_t rd_len,
                          uint32_t wr_addr, uint16_t wr_len);
 
-       int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap,
+       int (*as102_read_ep2) (struct as10x_bus_adapter_t *bus_adap,
                               unsigned char *recv_buf,
                               int recv_buf_len);
 };
index 3dedb3c1420a24308a5ae07b588d05b5ec8e9aaf..fde8140ae88b9406080b400e8ecb0ad609ae5e4b 100644 (file)
 /*********************************/
 
 /* bandwidth constant values */
-#define BW_5_MHZ           0x00
-#define BW_6_MHZ           0x01
-#define BW_7_MHZ           0x02
-#define BW_8_MHZ           0x03
+#define BW_5_MHZ               0x00
+#define BW_6_MHZ               0x01
+#define BW_7_MHZ               0x02
+#define BW_8_MHZ               0x03
 
 /* hierarchy priority selection values */
-#define HIER_NO_PRIORITY   0x00
-#define HIER_LOW_PRIORITY  0x01
-#define HIER_HIGH_PRIORITY 0x02
+#define HIER_NO_PRIORITY       0x00
+#define HIER_LOW_PRIORITY      0x01
+#define HIER_HIGH_PRIORITY     0x02
 
 /* constellation available values */
-#define CONST_QPSK         0x00
-#define CONST_QAM16        0x01
-#define CONST_QAM64        0x02
-#define CONST_UNKNOWN      0xFF
+#define CONST_QPSK             0x00
+#define CONST_QAM16            0x01
+#define CONST_QAM64            0x02
+#define CONST_UNKNOWN          0xFF
 
 /* hierarchy available values */
-#define HIER_NONE         0x00
-#define HIER_ALPHA_1      0x01
-#define HIER_ALPHA_2      0x02
-#define HIER_ALPHA_4      0x03
-#define HIER_UNKNOWN      0xFF
+#define HIER_NONE              0x00
+#define HIER_ALPHA_1           0x01
+#define HIER_ALPHA_2           0x02
+#define HIER_ALPHA_4           0x03
+#define HIER_UNKNOWN           0xFF
 
 /* interleaving available values */
-#define INTLV_NATIVE      0x00
-#define INTLV_IN_DEPTH    0x01
-#define INTLV_UNKNOWN     0xFF
+#define INTLV_NATIVE           0x00
+#define INTLV_IN_DEPTH         0x01
+#define INTLV_UNKNOWN          0xFF
 
 /* code rate available values */
-#define CODE_RATE_1_2     0x00
-#define CODE_RATE_2_3     0x01
-#define CODE_RATE_3_4     0x02
-#define CODE_RATE_5_6     0x03
-#define CODE_RATE_7_8     0x04
-#define CODE_RATE_UNKNOWN 0xFF
+#define CODE_RATE_1_2          0x00
+#define CODE_RATE_2_3          0x01
+#define CODE_RATE_3_4          0x02
+#define CODE_RATE_5_6          0x03
+#define CODE_RATE_7_8          0x04
+#define CODE_RATE_UNKNOWN      0xFF
 
 /* guard interval available values */
-#define GUARD_INT_1_32    0x00
-#define GUARD_INT_1_16    0x01
-#define GUARD_INT_1_8     0x02
-#define GUARD_INT_1_4     0x03
-#define GUARD_UNKNOWN     0xFF
+#define GUARD_INT_1_32         0x00
+#define GUARD_INT_1_16         0x01
+#define GUARD_INT_1_8          0x02
+#define GUARD_INT_1_4          0x03
+#define GUARD_UNKNOWN          0xFF
 
 /* transmission mode available values */
-#define TRANS_MODE_2K      0x00
-#define TRANS_MODE_8K      0x01
-#define TRANS_MODE_4K      0x02
-#define TRANS_MODE_UNKNOWN 0xFF
+#define TRANS_MODE_2K          0x00
+#define TRANS_MODE_8K          0x01
+#define TRANS_MODE_4K          0x02
+#define TRANS_MODE_UNKNOWN     0xFF
 
 /* DVBH signalling available values */
-#define TIMESLICING_PRESENT   0x01
-#define MPE_FEC_PRESENT       0x02
+#define TIMESLICING_PRESENT    0x01
+#define MPE_FEC_PRESENT                0x02
 
 /* tune state available */
-#define TUNE_STATUS_NOT_TUNED       0x00
-#define TUNE_STATUS_IDLE            0x01
-#define TUNE_STATUS_LOCKING         0x02
-#define TUNE_STATUS_SIGNAL_DVB_OK   0x03
-#define TUNE_STATUS_STREAM_DETECTED 0x04
-#define TUNE_STATUS_STREAM_TUNED    0x05
-#define TUNE_STATUS_ERROR           0xFF
+#define TUNE_STATUS_NOT_TUNED          0x00
+#define TUNE_STATUS_IDLE               0x01
+#define TUNE_STATUS_LOCKING            0x02
+#define TUNE_STATUS_SIGNAL_DVB_OK      0x03
+#define TUNE_STATUS_STREAM_DETECTED    0x04
+#define TUNE_STATUS_STREAM_TUNED       0x05
+#define TUNE_STATUS_ERROR              0xFF
 
 /* available TS FID filter types */
-#define TS_PID_TYPE_TS       0
-#define TS_PID_TYPE_PSI_SI   1
-#define TS_PID_TYPE_MPE      2
+#define TS_PID_TYPE_TS         0
+#define TS_PID_TYPE_PSI_SI     1
+#define TS_PID_TYPE_MPE                2
 
 /* number of echos available */
-#define MAX_ECHOS   15
+#define MAX_ECHOS      15
 
 /* Context types */
-#define CONTEXT_LNA                   1010
-#define CONTEXT_ELNA_HYSTERESIS       4003
-#define CONTEXT_ELNA_GAIN             4004
-#define CONTEXT_MER_THRESHOLD         5005
-#define CONTEXT_MER_OFFSET            5006
-#define CONTEXT_IR_STATE              7000
-#define CONTEXT_TSOUT_MSB_FIRST       7004
-#define CONTEXT_TSOUT_FALLING_EDGE    7005
+#define CONTEXT_LNA                    1010
+#define CONTEXT_ELNA_HYSTERESIS                4003
+#define CONTEXT_ELNA_GAIN              4004
+#define CONTEXT_MER_THRESHOLD          5005
+#define CONTEXT_MER_OFFSET             5006
+#define CONTEXT_IR_STATE               7000
+#define CONTEXT_TSOUT_MSB_FIRST                7004
+#define CONTEXT_TSOUT_FALLING_EDGE     7005
 
 /* Configuration modes */
-#define CFG_MODE_ON     0
-#define CFG_MODE_OFF    1
-#define CFG_MODE_AUTO   2
+#define CFG_MODE_ON    0
+#define CFG_MODE_OFF   1
+#define CFG_MODE_AUTO  2
 
-#pragma pack(1)
 struct as10x_tps {
-   uint8_t constellation;
-   uint8_t hierarchy;
-   uint8_t interleaving_mode;
-   uint8_t code_rate_HP;
-   uint8_t code_rate_LP;
-   uint8_t guard_interval;
-   uint8_t transmission_mode;
-   uint8_t DVBH_mask_HP;
-   uint8_t DVBH_mask_LP;
-   uint16_t cell_ID;
-};
+       uint8_t modulation;
+       uint8_t hierarchy;
+       uint8_t interleaving_mode;
+       uint8_t code_rate_HP;
+       uint8_t code_rate_LP;
+       uint8_t guard_interval;
+       uint8_t transmission_mode;
+       uint8_t DVBH_mask_HP;
+       uint8_t DVBH_mask_LP;
+       uint16_t cell_ID;
+} __packed;
 
 struct as10x_tune_args {
-   /* frequency */
-   uint32_t freq;
-   /* bandwidth */
-   uint8_t bandwidth;
-   /* hierarchy selection */
-   uint8_t hier_select;
-   /* constellation */
-   uint8_t constellation;
-   /* hierarchy */
-   uint8_t hierarchy;
-   /* interleaving mode */
-   uint8_t interleaving_mode;
-   /* code rate */
-   uint8_t code_rate;
-   /* guard interval */
-   uint8_t guard_interval;
-   /* transmission mode */
-   uint8_t transmission_mode;
-};
+       /* frequency */
+       uint32_t freq;
+       /* bandwidth */
+       uint8_t bandwidth;
+       /* hierarchy selection */
+       uint8_t hier_select;
+       /* constellation */
+       uint8_t modulation;
+       /* hierarchy */
+       uint8_t hierarchy;
+       /* interleaving mode */
+       uint8_t interleaving_mode;
+       /* code rate */
+       uint8_t code_rate;
+       /* guard interval */
+       uint8_t guard_interval;
+       /* transmission mode */
+       uint8_t transmission_mode;
+} __packed;
 
 struct as10x_tune_status {
-   /* tune status */
-   uint8_t tune_state;
-   /* signal strength */
-   int16_t signal_strength;
-   /* packet error rate 10^-4 */
-   uint16_t PER;
-   /* bit error rate 10^-4 */
-   uint16_t BER;
-};
+       /* tune status */
+       uint8_t tune_state;
+       /* signal strength */
+       int16_t signal_strength;
+       /* packet error rate 10^-4 */
+       uint16_t PER;
+       /* bit error rate 10^-4 */
+       uint16_t BER;
+} __packed;
 
 struct as10x_demod_stats {
-   /* frame counter */
-   uint32_t frame_count;
-   /* Bad frame counter */
-   uint32_t bad_frame_count;
-   /* Number of wrong bytes fixed by Reed-Solomon */
-   uint32_t bytes_fixed_by_rs;
-   /* Averaged MER */
-   uint16_t mer;
-   /* statistics calculation state indicator (started or not) */
-   uint8_t has_started;
-};
+       /* frame counter */
+       uint32_t frame_count;
+       /* Bad frame counter */
+       uint32_t bad_frame_count;
+       /* Number of wrong bytes fixed by Reed-Solomon */
+       uint32_t bytes_fixed_by_rs;
+       /* Averaged MER */
+       uint16_t mer;
+       /* statistics calculation state indicator (started or not) */
+       uint8_t has_started;
+} __packed;
 
 struct as10x_ts_filter {
-   uint16_t pid;  /** valid PID value 0x00 : 0x2000 */
-   uint8_t  type; /** Red TS_PID_TYPE_<N> values */
-   uint8_t  idx;  /** index in filtering table */
-};
+       uint16_t pid;  /* valid PID value 0x00 : 0x2000 */
+       uint8_t  type; /* Red TS_PID_TYPE_<N> values */
+       uint8_t  idx;  /* index in filtering table */
+} __packed;
 
 struct as10x_register_value {
-   uint8_t       mode;
-   union {
-      uint8_t    value8;    /* 8 bit value */
-      uint16_t   value16;   /* 16 bit value */
-      uint32_t   value32;   /* 32 bit value */
-   }u;
-};
-
-#pragma pack()
+       uint8_t mode;
+       union {
+               uint8_t  value8;   /* 8 bit value */
+               uint16_t value16;  /* 16 bit value */
+               uint32_t value32;  /* 32 bit value */
+       } u;
+} __packed;
 
 struct as10x_register_addr {
-   /* register addr */
-   uint32_t addr;
-   /* register mode access */
-   uint8_t mode;
+       /* register addr */
+       uint32_t addr;
+       /* register mode access */
+       uint8_t mode;
 };
 
-
 #endif
index 04e93c49f03a88af2d9b716fa70488461526189a..280c84ec4cc2c0ece47161f69547b03e62759ab6 100644 (file)
@@ -218,9 +218,10 @@ dt3155_start_acq(struct dt3155_priv *pd)
  *     driver-specific callbacks (vb2_ops)
  */
 static int
-dt3155_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
-                       unsigned int *num_planes, unsigned long sizes[],
-                                               void *alloc_ctxs[])
+dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+               unsigned int *num_buffers, unsigned int *num_planes,
+               unsigned int sizes[], void *alloc_ctxs[])
+
 {
        struct dt3155_priv *pd = vb2_get_drv_priv(q);
        void *ret;
@@ -261,12 +262,6 @@ dt3155_buf_prepare(struct vb2_buffer *vb)
        return 0;
 }
 
-static int
-dt3155_start_streaming(struct vb2_queue *q)
-{
-       return 0;
-}
-
 static int
 dt3155_stop_streaming(struct vb2_queue *q)
 {
@@ -308,7 +303,6 @@ const struct vb2_ops q_ops = {
        .wait_prepare = dt3155_wait_prepare,
        .wait_finish = dt3155_wait_finish,
        .buf_prepare = dt3155_buf_prepare,
-       .start_streaming = dt3155_start_streaming,
        .stop_streaming = dt3155_stop_streaming,
        .buf_queue = dt3155_buf_queue,
 };
@@ -914,9 +908,10 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (err)
                goto err_req_region;
        pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
-       if (!pd->regs)
+       if (!pd->regs) {
                err = -ENOMEM;
                goto err_pci_iomap;
+       }
        err = dt3155_init_board(pdev);
        if (err)
                goto err_init_board;
index 7b256a948c2758246d9983bab460c754d1c971b4..a007e7442be87d9a2d3b9bcff31726aae17b109f 100644 (file)
@@ -98,7 +98,6 @@
 #define EASYCAP_DRIVER_VERSION "0.9.01"
 #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
 
-#define USB_SKEL_MINOR_BASE     192
 #define DONGLE_MANY 8
 #define INPUT_MANY 6
 /*---------------------------------------------------------------------------*/
@@ -324,8 +323,6 @@ struct easycap {
        int lost[INPUT_MANY];
        int merit[180];
 
-       long long int dnbydt;
-
        int    video_interface;
        int    video_altsetting_on;
        int    video_altsetting_off;
@@ -353,7 +350,6 @@ struct easycap {
        u8 *pcache;
        int video_mt;
        int audio_mt;
-       long long audio_bytes;
        u32 isequence;
 
        int vma_many;
@@ -450,9 +446,6 @@ struct easycap {
  *  SOUND PROPERTIES
  */
 /*---------------------------------------------------------------------------*/
-
-       int audio_buffer_many;
-
        int allocation_audio_urb;
        int allocation_audio_page;
        int allocation_audio_struct;
@@ -469,72 +462,53 @@ struct easycap {
  *  VIDEO FUNCTION PROTOTYPES
  */
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+int easycap_newinput(struct easycap *, int);
+void easycap_testcard(struct easycap *, int);
+int easycap_isdongle(struct easycap *);
+
 long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long);
-int              easycap_dqbuf(struct easycap *, int);
-int              submit_video_urbs(struct easycap *);
-int              kill_video_urbs(struct easycap *);
-int              field2frame(struct easycap *);
-int              redaub(struct easycap *, void *, void *,
-                                               int, int, u8, u8, bool);
-void             easycap_testcard(struct easycap *, int);
-int              fillin_formats(void);
-int              newinput(struct easycap *, int);
-int              adjust_standard(struct easycap *, v4l2_std_id);
-int              adjust_format(struct easycap *, u32, u32, u32,
-                                                               int, bool);
-int              adjust_brightness(struct easycap *, int);
-int              adjust_contrast(struct easycap *, int);
-int              adjust_saturation(struct easycap *, int);
-int              adjust_hue(struct easycap *, int);
-int              adjust_volume(struct easycap *, int);
+
+int easycap_video_dqbuf(struct easycap *, int);
+int easycap_video_submit_urbs(struct easycap *);
+int easycap_video_kill_urbs(struct easycap *);
+int easycap_video_fillin_formats(void);
+
+int adjust_standard(struct easycap *, v4l2_std_id);
+int adjust_format(struct easycap *, u32, u32, u32, int, bool);
+int adjust_brightness(struct easycap *, int);
+int adjust_contrast(struct easycap *, int);
+int adjust_saturation(struct easycap *, int);
+int adjust_hue(struct easycap *, int);
 /*---------------------------------------------------------------------------*/
 /*
  *  AUDIO FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-int            easycap_alsa_probe(struct easycap *);
-void            easycap_alsa_complete(struct urb *);
-
-int              easycap_sound_setup(struct easycap *);
-int              submit_audio_urbs(struct easycap *);
-int              kill_audio_urbs(struct easycap *);
-void             easyoss_testtone(struct easycap *, int);
-int              audio_setup(struct easycap *);
+int easycap_alsa_probe(struct easycap *);
+int easycap_audio_kill_urbs(struct easycap *);
+void easycap_alsa_complete(struct urb *);
 /*---------------------------------------------------------------------------*/
 /*
  *  LOW-LEVEL FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-int              audio_gainget(struct usb_device *);
-int              audio_gainset(struct usb_device *, s8);
+int easycap_audio_gainset(struct usb_device *, s8);
+int easycap_audio_setup(struct easycap *);
 
-int              set_interface(struct usb_device *, u16);
-int              wakeup_device(struct usb_device *);
-int              confirm_resolution(struct usb_device *);
-int              confirm_stream(struct usb_device *);
+int easycap_wakeup_device(struct usb_device *);
 
-int              setup_stk(struct usb_device *, bool);
-int              setup_saa(struct usb_device *, bool);
-int              setup_vt(struct usb_device *);
-int              check_stk(struct usb_device *, bool);
-int              check_saa(struct usb_device *, bool);
-int              ready_saa(struct usb_device *);
-int              merit_saa(struct usb_device *);
-int              check_vt(struct usb_device *);
-int              select_input(struct usb_device *, int, int);
-int              set_resolution(struct usb_device *,
-                                               u16, u16, u16, u16);
+int setup_stk(struct usb_device *, bool);
+int setup_saa(struct usb_device *, bool);
+int ready_saa(struct usb_device *);
+int merit_saa(struct usb_device *);
+int check_vt(struct usb_device *);
+int select_input(struct usb_device *, int, int);
+int set_resolution(struct usb_device *, u16, u16, u16, u16);
 
-int              read_saa(struct usb_device *, u16);
-int              read_stk(struct usb_device *, u32);
-int              write_saa(struct usb_device *, u16, u16);
-int              write_000(struct usb_device *, u16, u16);
-int              start_100(struct usb_device *);
-int              stop_100(struct usb_device *);
-int              write_300(struct usb_device *);
-int              read_vt(struct usb_device *, u16);
-int              write_vt(struct usb_device *, u16, u16);
-int            isdongle(struct easycap *);
+int read_saa(struct usb_device *, u16);
+int write_saa(struct usb_device *, u16, u16);
+int start_100(struct usb_device *);
+int stop_100(struct usb_device *);
 /*---------------------------------------------------------------------------*/
 
 
@@ -588,7 +562,6 @@ extern bool easycap_readback;
 extern const struct easycap_standard easycap_standard[];
 extern struct easycap_format easycap_format[];
 extern struct v4l2_queryctrl easycap_control[];
-extern struct usb_driver easycap_usb_driver;
 extern struct easycap_dongle easycapdc60_dongle[];
 
 #endif /* !__EASYCAP_H__  */
index c99addfb62428888bd089de3a96b43b6e20a8500..9413b37490c2f2468e726d8056cddf6b9a33293f 100644 (file)
@@ -25,7 +25,6 @@
 */
 /*****************************************************************************/
 
-#include <linux/version.h>
 #include "easycap.h"
 
 /*--------------------------------------------------------------------------*/
@@ -125,7 +124,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
        }
        if (peasycap->video_isoc_streaming) {
                resubmit = true;
-               kill_video_urbs(peasycap);
+               easycap_video_kill_urbs(peasycap);
        } else
                resubmit = false;
 /*--------------------------------------------------------------------------*/
@@ -331,7 +330,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
                            "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
        }
        if (resubmit)
-               submit_video_urbs(peasycap);
+               easycap_video_submit_urbs(peasycap);
        return 0;
 }
 /*****************************************************************************/
@@ -558,7 +557,7 @@ int adjust_format(struct easycap *peasycap,
                peasycap->bytesperpixel * peasycap->width * peasycap->height;
        if (peasycap->video_isoc_streaming) {
                resubmit = true;
-               kill_video_urbs(peasycap);
+               easycap_video_kill_urbs(peasycap);
        } else
                resubmit = false;
 /*---------------------------------------------------------------------------*/
@@ -622,7 +621,7 @@ int adjust_format(struct easycap *peasycap,
        }
 /*---------------------------------------------------------------------------*/
        if (resubmit)
-               submit_video_urbs(peasycap);
+               easycap_video_submit_urbs(peasycap);
 
        return peasycap_best_format - easycap_format;
 }
@@ -667,16 +666,15 @@ int adjust_brightness(struct easycap *peasycap, int value)
                                peasycap->inputset[peasycap->input].brightness_ok = 1;
                        } else
                                JOM(8, "%i=peasycap->input\n", peasycap->input);
+
                        mood = 0x00FF & (unsigned int)peasycap->brightness;
-                       if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
-                               SAM("adjusting brightness to  0x%02X\n", mood);
-                               return 0;
-                       } else {
+                       if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
                                SAM("WARNING: failed to adjust brightness "
                                    "to 0x%02X\n", mood);
                                return -ENOENT;
                        }
-                       break;
+                       SAM("adjusting brightness to  0x%02X\n", mood);
+                       return 0;
                }
                i1++;
        }
@@ -726,15 +724,13 @@ int adjust_contrast(struct easycap *peasycap, int value)
                                JOM(8, "%i=peasycap->input\n", peasycap->input);
 
                        mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
-                       if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
-                               SAM("adjusting contrast to  0x%02X\n", mood);
-                               return 0;
-                       } else {
+                       if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
                                SAM("WARNING: failed to adjust contrast to "
                                    "0x%02X\n", mood);
                                return -ENOENT;
                        }
-                       break;
+                       SAM("adjusting contrast to  0x%02X\n", mood);
+                       return 0;
                }
                i1++;
        }
@@ -784,14 +780,13 @@ int adjust_saturation(struct easycap *peasycap, int value)
                        } else
                                JOM(8, "%i=peasycap->input\n", peasycap->input);
                        mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
-                       if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
-                               SAM("adjusting saturation to  0x%02X\n", mood);
-                               return 0;
-                       } else {
+                       if (write_saa(peasycap->pusb_device, 0x0C, mood)) {
                                SAM("WARNING: failed to adjust saturation to "
                                    "0x%02X\n", mood);
                                return -ENOENT;
                        }
+                       SAM("adjusting saturation to  0x%02X\n", mood);
+                       return 0;
                        break;
                }
                i1++;
@@ -839,13 +834,12 @@ int adjust_hue(struct easycap *peasycap, int value)
                                JOM(8, "%i=peasycap->input\n", peasycap->input);
                        i2 = peasycap->hue - 128;
                        mood = 0x00FF & ((int) i2);
-                       if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
-                               SAM("adjusting hue to  0x%02X\n", mood);
-                               return 0;
-                       } else {
+                       if (write_saa(peasycap->pusb_device, 0x0D, mood)) {
                                SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
                                return -ENOENT;
                        }
+                       SAM("adjusting hue to  0x%02X\n", mood);
+                       return 0;
                        break;
                }
                i1++;
@@ -854,7 +848,7 @@ int adjust_hue(struct easycap *peasycap, int value)
        return -ENOENT;
 }
 /*****************************************************************************/
-int adjust_volume(struct easycap *peasycap, int value)
+static int adjust_volume(struct easycap *peasycap, int value)
 {
        s8 mood;
        int i1;
@@ -885,15 +879,13 @@ int adjust_volume(struct easycap *peasycap, int value)
                        mood = (16 > peasycap->volume) ? 16 :
                                ((31 < peasycap->volume) ? 31 :
                                  (s8) peasycap->volume);
-                       if (!audio_gainset(peasycap->pusb_device, mood)) {
-                               SAM("adjusting volume to 0x%02X\n", mood);
-                               return 0;
-                       } else {
+                       if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
                                SAM("WARNING: failed to adjust volume to "
                                    "0x%2X\n", mood);
                                return -ENOENT;
                        }
-                       break;
+                       SAM("adjusting volume to 0x%02X\n", mood);
+                       return 0;
                }
                i1++;
        }
@@ -971,7 +963,7 @@ long easycap_unlocked_ioctl(struct file *file,
                SAM("ERROR: peasycap->pusb_device is NULL\n");
                return -EFAULT;
        }
-       kd = isdongle(peasycap);
+       kd = easycap_isdongle(peasycap);
        if (0 <= kd && DONGLE_MANY > kd) {
                if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
                        SAY("ERROR: cannot lock "
@@ -986,7 +978,7 @@ long easycap_unlocked_ioctl(struct file *file,
  *  IF NECESSARY, BAIL OUT.
  */
 /*---------------------------------------------------------------------------*/
-               if (kd != isdongle(peasycap))
+               if (kd != easycap_isdongle(peasycap))
                        return -ERESTARTSYS;
                if (!file) {
                        SAY("ERROR:  file is NULL\n");
@@ -1226,7 +1218,7 @@ long easycap_unlocked_ioctl(struct file *file,
                        return -EINVAL;
                }
 
-               rc = newinput(peasycap, (int)index);
+               rc = easycap_newinput(peasycap, (int)index);
                if (0 == rc) {
                        JOM(8, "newinput(.,%i) OK\n", (int)index);
                } else {
@@ -2209,7 +2201,7 @@ long easycap_unlocked_ioctl(struct file *file,
 
                if (!peasycap->polled) {
                        do {
-                               rcdq = easycap_dqbuf(peasycap, 0);
+                               rcdq = easycap_video_dqbuf(peasycap, 0);
                                if (-EIO == rcdq) {
                                        JOM(8, "returning -EIO because "
                                            "dqbuf() returned -EIO\n");
@@ -2313,7 +2305,7 @@ long easycap_unlocked_ioctl(struct file *file,
                        mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
                        return -EFAULT;
                }
-               submit_video_urbs(peasycap);
+               easycap_video_submit_urbs(peasycap);
                peasycap->video_idle = 0;
                peasycap->audio_idle = 0;
                peasycap->video_eof = 0;
index 0385735ac6df8a56d0a0a7f306941afdce47f6fb..0380babed22c02b62db3c8f7ceb1096ad24d4190 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "easycap.h"
 
+
 #define GET(X, Y, Z) do { \
        int __rc; \
        *(Z) = (u16)0; \
@@ -59,9 +60,9 @@
 
 /*--------------------------------------------------------------------------*/
 static const struct stk1160config {
-       int reg;
-       int set;
-} stk1160configPAL[256] = {
+       u16 reg;
+       u16 set;
+} stk1160configPAL[] = {
                {0x000, 0x0098},
                {0x002, 0x0093},
 
@@ -103,7 +104,7 @@ static const struct stk1160config {
                {0xFFF, 0xFFFF}
 };
 /*--------------------------------------------------------------------------*/
-static const struct stk1160config stk1160configNTSC[256] = {
+static const struct stk1160config stk1160configNTSC[] = {
                {0x000, 0x0098},
                {0x002, 0x0093},
 
@@ -146,9 +147,9 @@ static const struct stk1160config stk1160configNTSC[256] = {
 };
 /*--------------------------------------------------------------------------*/
 static const struct saa7113config {
-       int reg;
-       int set;
-} saa7113configPAL[256] = {
+       u8 reg;
+       u8 set;
+} saa7113configPAL[] = {
                {0x01, 0x08},
                {0x02, 0x80},
                {0x03, 0x33},
@@ -202,7 +203,7 @@ static const struct saa7113config {
                {0xFF, 0xFF}
 };
 /*--------------------------------------------------------------------------*/
-static const struct saa7113config saa7113configNTSC[256] = {
+static const struct saa7113config saa7113configNTSC[] = {
                {0x01, 0x08},
                {0x02, 0x80},
                {0x03, 0x33},
@@ -354,101 +355,6 @@ static int wait_i2c(struct usb_device *p)
        return -1;
 }
 
-/****************************************************************************/
-int confirm_resolution(struct usb_device *p)
-{
-       u8 get0, get1, get2, get3, get4, get5, get6, get7;
-
-       if (!p)
-               return -ENODEV;
-       GET(p, 0x0110, &get0);
-       GET(p, 0x0111, &get1);
-       GET(p, 0x0112, &get2);
-       GET(p, 0x0113, &get3);
-       GET(p, 0x0114, &get4);
-       GET(p, 0x0115, &get5);
-       GET(p, 0x0116, &get6);
-       GET(p, 0x0117, &get7);
-       JOT(8,  "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X\n",
-               get0, get1, get2, get3, get4, get5, get6, get7);
-       JOT(8,  "....cf PAL_720x526: "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X\n",
-               0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
-       JOT(8,  "....cf PAL_704x526: "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X\n",
-               0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
-       JOT(8,  "....cf VGA_640x480: "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X, "
-               "0x%03X, 0x%03X\n",
-               0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
-       return 0;
-}
-/****************************************************************************/
-int confirm_stream(struct usb_device *p)
-{
-       u16 get2;
-       u8 igot;
-
-       if (!p)
-               return -ENODEV;
-       GET(p, 0x0100, &igot);  get2 = 0x80 & igot;
-       if (0x80 == get2)
-               JOT(8, "confirm_stream:  OK\n");
-       else
-               JOT(8, "confirm_stream:  STUCK\n");
-       return 0;
-}
-/****************************************************************************/
-int setup_stk(struct usb_device *p, bool ntsc)
-{
-       int i;
-       const struct stk1160config *cfg;
-       if (!p)
-               return -ENODEV;
-       cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
-       for (i = 0; cfg[i].reg != 0xFFF; i++)
-               SET(p, cfg[i].reg, cfg[i].set);
-
-       write_300(p);
-
-       return 0;
-}
-/****************************************************************************/
-int setup_saa(struct usb_device *p, bool ntsc)
-{
-       int i, ir;
-       const struct saa7113config *cfg;
-       if (!p)
-               return -ENODEV;
-       cfg = (ntsc) ?  saa7113configNTSC : saa7113configPAL;
-       for (i = 0; cfg[i].reg != 0xFF; i++)
-               ir = write_saa(p, cfg[i].reg, cfg[i].set);
-       return 0;
-}
-/****************************************************************************/
-int write_000(struct usb_device *p, u16 set2, u16 set0)
-{
-       u8 igot0, igot2;
-
-       if (!p)
-               return -ENODEV;
-       GET(p, 0x0002, &igot2);
-       GET(p, 0x0000, &igot0);
-       SET(p, 0x0002, set2);
-       SET(p, 0x0000, set0);
-       return 0;
-}
 /****************************************************************************/
 int write_saa(struct usb_device *p, u16 reg0, u16 set0)
 {
@@ -470,8 +376,7 @@ int write_saa(struct usb_device *p, u16 reg0, u16 set0)
  *  REGISTER 504:  TARGET ADDRESS ON VT1612A
  */
 /*--------------------------------------------------------------------------*/
-int
-write_vt(struct usb_device *p, u16 reg0, u16 set0)
+static int write_vt(struct usb_device *p, u16 reg0, u16 set0)
 {
        u8 igot;
        u16 got502, got503;
@@ -508,7 +413,7 @@ write_vt(struct usb_device *p, u16 reg0, u16 set0)
  *  REGISTER 504:  TARGET ADDRESS ON VT1612A
  */
 /*--------------------------------------------------------------------------*/
-int read_vt(struct usb_device *p, u16 reg0)
+static int read_vt(struct usb_device *p, u16 reg0)
 {
        u8 igot;
        u16 got502, got503;
@@ -532,7 +437,7 @@ int read_vt(struct usb_device *p, u16 reg0)
  *  THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
  */
 /*--------------------------------------------------------------------------*/
-int write_300(struct usb_device *p)
+static int write_300(struct usb_device *p)
 {
        if (!p)
                return -ENODEV;
@@ -545,32 +450,36 @@ int write_300(struct usb_device *p)
        return 0;
 }
 /****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  NOTE: THE FOLLOWING IS NOT CHECKED:
- *  REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL.
- */
-/*--------------------------------------------------------------------------*/
-int check_saa(struct usb_device *p, bool ntsc)
+/****************************************************************************/
+int setup_stk(struct usb_device *p, bool ntsc)
 {
-       int i, ir, rc = 0;
-       struct saa7113config const *cfg;
+       int i;
+       const struct stk1160config *cfg;
        if (!p)
                return -ENODEV;
+       cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
+       for (i = 0; cfg[i].reg != 0xFFF; i++)
+               SET(p, cfg[i].reg, cfg[i].set);
+
+       write_300(p);
 
-       cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
+       return 0;
+}
+/****************************************************************************/
+int setup_saa(struct usb_device *p, bool ntsc)
+{
+       int i, rc;
+       const struct saa7113config *cfg;
+       if (!p)
+               return -ENODEV;
+       cfg = (ntsc) ?  saa7113configNTSC : saa7113configPAL;
        for (i = 0; cfg[i].reg != 0xFF; i++) {
-               if (0x0F == cfg[i].reg)
-                       continue;
-               ir = read_saa(p, cfg[i].reg);
-               if (ir != cfg[i].set) {
-                       SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n",
-                               cfg[i].reg, ir, cfg[i].set);
-                               rc--;
-               }
+               rc = write_saa(p, cfg[i].reg, cfg[i].set);
+               if (rc)
+                       dev_err(&p->dev,
+                               "Failed to set SAA register %d", cfg[i].reg);
        }
-
-       return (rc < -8) ? rc : 0;
+       return 0;
 }
 /****************************************************************************/
 int merit_saa(struct usb_device *p)
@@ -609,60 +518,22 @@ int ready_saa(struct usb_device *p)
                msleep(marktime);
                j++;
        }
+
        if (max == j)
                return -1;
-       else {
-               if (0x20 & rc) {
-                       rate = 2;
-                       JOT(8, "hardware detects 60 Hz\n");
-               } else {
-                       rate = 0;
-                       JOT(8, "hardware detects 50 Hz\n");
-               }
-               if (0x80 & rc)
-                       JOT(8, "hardware detects interlacing\n");
-               else {
-                       rate++;
-                       JOT(8, "hardware detects no interlacing\n");
-               }
-       }
-       return 0;
-}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  NOTE: THE FOLLOWING ARE NOT CHECKED:
- *  REGISTERS 0x000, 0x002:  FUNCTIONALITY IS NOT KNOWN
- *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config....[.].set)
- */
-/*--------------------------------------------------------------------------*/
-int check_stk(struct usb_device *p, bool ntsc)
-{
-       int i, ir;
-       const struct stk1160config *cfg;
-
-       if (!p)
-               return -ENODEV;
-       cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
-
-       for (i = 0; 0xFFF != cfg[i].reg; i++) {
-               if (0x000 == cfg[i].reg || 0x002 == cfg[i].reg)
-                       continue;
 
-
-               ir = read_stk(p, cfg[i].reg);
-               if (0x100 == cfg[i].reg) {
-                       if ((ir != (0xFF & cfg[i].set)) &&
-                           (ir != (0x80 | (0xFF & cfg[i].set))) &&
-                           (0xFFFF != cfg[i].set)) {
-                               SAY("STK reg[0x%03X]=0x%02X expected 0x%02X\n",
-                                       cfg[i].reg, ir, cfg[i].set);
-                       }
-                       continue;
-               }
-               if ((ir != (0xFF & cfg[i].set)) && (0xFFFF != cfg[i].set))
-                       SAY("STK register 0x%03X has 0x%02X,expected 0x%02X\n",
-                               cfg[i].reg, ir, cfg[i].set);
+       if (0x20 & rc) {
+               rate = 2;
+               JOT(8, "hardware detects 60 Hz\n");
+       } else {
+               rate = 0;
+               JOT(8, "hardware detects 50 Hz\n");
+       }
+       if (0x80 & rc)
+               JOT(8, "hardware detects interlacing\n");
+       else {
+               rate++;
+               JOT(8, "hardware detects no interlacing\n");
        }
        return 0;
 }
@@ -682,7 +553,7 @@ int read_saa(struct usb_device *p, u16 reg0)
        return igot;
 }
 /****************************************************************************/
-int read_stk(struct usb_device *p, u32 reg0)
+static int read_stk(struct usb_device *p, u32 reg0)
 {
        u8 igot;
 
@@ -692,27 +563,7 @@ int read_stk(struct usb_device *p, u32 reg0)
        GET(p, reg0, &igot);
        return igot;
 }
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *    HARDWARE    USERSPACE INPUT NUMBER   PHYSICAL INPUT   DRIVER input VALUE
- *
- *  CVBS+S-VIDEO           0 or 1              CVBS                 1
- *   FOUR-CVBS             0 or 1              CVBS1                1
- *   FOUR-CVBS                2                CVBS2                2
- *   FOUR-CVBS                3                CVBS3                3
- *   FOUR-CVBS                4                CVBS4                4
- *  CVBS+S-VIDEO              5               S-VIDEO               5
- *
- *  WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED:
- *
- *     mode  7   => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED)
- *     mode  9   => USE AUTOMATIC GAIN CONTROL (DEFAULT)
- *
-*/
-/*---------------------------------------------------------------------------*/
-int
-select_input(struct usb_device *p, int input, int mode)
+int select_input(struct usb_device *p, int input, int mode)
 {
        int ir;
 
@@ -877,10 +728,11 @@ int stop_100(struct usb_device *p)
 /****************************************************************************/
 /****************************************************************************/
 /*****************************************************************************/
-int wakeup_device(struct usb_device *pusb_device)
+int easycap_wakeup_device(struct usb_device *pusb_device)
 {
        if (!pusb_device)
                return -ENODEV;
+
        return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
                        USB_REQ_SET_FEATURE,
                        USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
@@ -888,8 +740,7 @@ int wakeup_device(struct usb_device *pusb_device)
                        0, NULL, 0, 50000);
 }
 /*****************************************************************************/
-int
-audio_setup(struct easycap *peasycap)
+int easycap_audio_setup(struct easycap *peasycap)
 {
        struct usb_device *pusb_device;
        u8 buffer[1];
@@ -970,7 +821,7 @@ audio_setup(struct easycap *peasycap)
  *  SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
 */
 /*---------------------------------------------------------------------------*/
-       if (0 != audio_gainset(pusb_device, peasycap->gain))
+       if (easycap_audio_gainset(pusb_device, peasycap->gain))
                SAY("ERROR: audio_gainset() failed\n");
        check_vt(pusb_device);
        return 0;
@@ -1047,7 +898,7 @@ int check_vt(struct usb_device *pusb_device)
  *        31                12.0                  22.5            34.5
 */
 /*---------------------------------------------------------------------------*/
-int audio_gainset(struct usb_device *pusb_device, s8 loud)
+int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud)
 {
        int igot;
        u8 tmp;
@@ -1115,15 +966,3 @@ int audio_gainset(struct usb_device *pusb_device, s8 loud)
        return 0;
 }
 /*****************************************************************************/
-int audio_gainget(struct usb_device *pusb_device)
-{
-       int igot;
-
-       if (!pusb_device)
-               return -ENODEV;
-       igot = read_vt(pusb_device, 0x001C);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x1C\n");
-       return igot;
-}
-/*****************************************************************************/
index a45c0b5070678785196fa1c9e2fd04ed77f964dd..8ff5f38ea1964302af28c1d6d47fba5ffa5f4376 100644 (file)
@@ -66,6 +66,10 @@ struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
 static struct mutex mutex_dongle;
 static void easycap_complete(struct urb *purb);
 static int reset(struct easycap *peasycap);
+static int field2frame(struct easycap *peasycap);
+static int redaub(struct easycap *peasycap,
+               void *pad, void *pex, int much, int more,
+               u8 mask, u8 margin, bool isuy);
 
 const char *strerror(int err)
 {
@@ -109,23 +113,13 @@ const char *strerror(int err)
 #undef ERRNOSTR
 }
 
-/*---------------------------------------------------------------------------*/
-/*
- *  PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
- *
- *  NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
- *        CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
- *        THIS IS THE CASE FOR OpenSUSE.
- */
-/*---------------------------------------------------------------------------*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
 */
 /*---------------------------------------------------------------------------*/
-int isdongle(struct easycap *peasycap)
+int easycap_isdongle(struct easycap *peasycap)
 {
        int k;
        if (!peasycap)
@@ -161,14 +155,13 @@ static int easycap_open(struct inode *inode, struct file *file)
        if (!peasycap->pusb_device) {
                SAM("ERROR: peasycap->pusb_device is NULL\n");
                return -EFAULT;
-       } else {
-               JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
        }
+
+       JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
+
        file->private_data = peasycap;
-       rc = wakeup_device(peasycap->pusb_device);
-       if (0 == rc)
-               JOM(8, "wakeup_device() OK\n");
-       else {
+       rc = easycap_wakeup_device(peasycap->pusb_device);
+       if (rc) {
                SAM("ERROR: wakeup_device() rc = %i\n", rc);
                if (-ENODEV == rc)
                        SAM("ERROR: wakeup_device() returned -ENODEV\n");
@@ -176,6 +169,7 @@ static int easycap_open(struct inode *inode, struct file *file)
                        SAM("ERROR: wakeup_device() rc = %i\n", rc);
                return rc;
        }
+       JOM(8, "wakeup_device() OK\n");
        peasycap->input = 0;
        rc = reset(peasycap);
        if (rc) {
@@ -303,7 +297,7 @@ static int reset(struct easycap *peasycap)
        peasycap->saturation = -8192;
        peasycap->hue = -8192;
 
-       rc = newinput(peasycap, input);
+       rc = easycap_newinput(peasycap, input);
 
        if (rc) {
                SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
@@ -364,8 +358,7 @@ static int reset(struct easycap *peasycap)
  *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
 */
 /*---------------------------------------------------------------------------*/
-int
-newinput(struct easycap *peasycap, int input)
+int easycap_newinput(struct easycap *peasycap, int input)
 {
        int rc, k, m, mood, off;
        int inputnow, video_idlenow, audio_idlenow;
@@ -397,7 +390,7 @@ newinput(struct easycap *peasycap, int input)
        peasycap->audio_idle = 1;
        if (peasycap->video_isoc_streaming) {
                resubmit = true;
-               kill_video_urbs(peasycap);
+               easycap_video_kill_urbs(peasycap);
        } else {
                resubmit = false;
        }
@@ -532,7 +525,7 @@ newinput(struct easycap *peasycap, int input)
                return -EFAULT;
        }
        if (resubmit)
-               submit_video_urbs(peasycap);
+               easycap_video_submit_urbs(peasycap);
 
        peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
        peasycap->video_idle = video_idlenow;
@@ -542,7 +535,7 @@ newinput(struct easycap *peasycap, int input)
        return 0;
 }
 /*****************************************************************************/
-int submit_video_urbs(struct easycap *peasycap)
+int easycap_video_submit_urbs(struct easycap *peasycap)
 {
        struct data_urb *pdata_urb;
        struct urb *purb;
@@ -616,43 +609,53 @@ int submit_video_urbs(struct easycap *peasycap)
                        peasycap->video_eof = 1;
                }
 
-               if (isbad) {
-                       JOM(4, "attempting cleanup instead of submitting\n");
-                       list_for_each(plist_head, (peasycap->purb_video_head)) {
-                               pdata_urb = list_entry(plist_head,
-                                               struct data_urb, list_head);
-                               if (pdata_urb) {
-                                       purb = pdata_urb->purb;
-                                       if (purb)
-                                               usb_kill_urb(purb);
-                               }
-                       }
-                       peasycap->video_isoc_streaming = 0;
-               } else {
+               if (isbad)
+                       easycap_video_kill_urbs(peasycap);
+               else
                        peasycap->video_isoc_streaming = 1;
-                       JOM(4, "submitted %i video urbs\n", m);
-               }
        } else {
                JOM(4, "already streaming video urbs\n");
        }
        return 0;
 }
 /*****************************************************************************/
-int kill_video_urbs(struct easycap *peasycap)
+int easycap_audio_kill_urbs(struct easycap *peasycap)
 {
        int m;
        struct list_head *plist_head;
        struct data_urb *pdata_urb;
 
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
+       if (!peasycap->audio_isoc_streaming)
+               return 0;
+
+       if (!peasycap->purb_audio_head) {
+               SAM("ERROR: peasycap->purb_audio_head is NULL\n");
                return -EFAULT;
        }
-       if (!peasycap->video_isoc_streaming) {
-               JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
-                       peasycap->video_isoc_streaming);
-               return 0;
+
+       peasycap->audio_isoc_streaming = 0;
+       m = 0;
+       list_for_each(plist_head, peasycap->purb_audio_head) {
+               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
+               if (pdata_urb && pdata_urb->purb) {
+                       usb_kill_urb(pdata_urb->purb);
+                       m++;
+               }
        }
+
+       JOM(4, "%i audio urbs killed\n", m);
+
+       return 0;
+}
+int easycap_video_kill_urbs(struct easycap *peasycap)
+{
+       int m;
+       struct list_head *plist_head;
+       struct data_urb *pdata_urb;
+
+       if (!peasycap->video_isoc_streaming)
+               return 0;
+
        if (!peasycap->purb_video_head) {
                SAM("ERROR: peasycap->purb_video_head is NULL\n");
                return -EFAULT;
@@ -690,8 +693,8 @@ static int videodev_release(struct video_device *pvideo_device)
                SAY("ending unsuccessfully\n");
                return -EFAULT;
        }
-       if (0 != kill_video_urbs(peasycap)) {
-               SAM("ERROR: kill_video_urbs() failed\n");
+       if (easycap_video_kill_urbs(peasycap)) {
+               SAM("ERROR: easycap_video_kill_urbs() failed\n");
                return -EFAULT;
        }
        JOM(4, "ending successfully\n");
@@ -727,27 +730,22 @@ static void easycap_delete(struct kref *pkref)
                SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
                return;
        }
-       kd = isdongle(peasycap);
+       kd = easycap_isdongle(peasycap);
 /*---------------------------------------------------------------------------*/
 /*
  *  FREE VIDEO.
  */
 /*---------------------------------------------------------------------------*/
        if (peasycap->purb_video_head) {
-               JOM(4, "freeing video urbs\n");
                m = 0;
-               list_for_each(plist_head, (peasycap->purb_video_head)) {
+               list_for_each(plist_head, peasycap->purb_video_head) {
                        pdata_urb = list_entry(plist_head,
                                                struct data_urb, list_head);
-                       if (!pdata_urb) {
-                               JOM(4, "ERROR: pdata_urb is NULL\n");
-                       } else {
-                               if (pdata_urb->purb) {
-                                       usb_free_urb(pdata_urb->purb);
-                                       pdata_urb->purb = NULL;
-                                       peasycap->allocation_video_urb -= 1;
-                                       m++;
-                               }
+                       if (pdata_urb && pdata_urb->purb) {
+                               usb_free_urb(pdata_urb->purb);
+                               pdata_urb->purb = NULL;
+                               peasycap->allocation_video_urb--;
+                               m++;
                        }
                }
 
@@ -763,7 +761,6 @@ static void easycap_delete(struct kref *pkref)
                                peasycap->allocation_video_struct -=
                                                sizeof(struct data_urb);
                                kfree(pdata_urb);
-                               pdata_urb = NULL;
                                m++;
                        }
                }
@@ -828,15 +825,11 @@ static void easycap_delete(struct kref *pkref)
                list_for_each(plist_head, (peasycap->purb_audio_head)) {
                        pdata_urb = list_entry(plist_head,
                                        struct data_urb, list_head);
-                       if (!pdata_urb)
-                               JOM(4, "ERROR: pdata_urb is NULL\n");
-                       else {
-                               if (pdata_urb->purb) {
-                                       usb_free_urb(pdata_urb->purb);
-                                       pdata_urb->purb = NULL;
-                                       peasycap->allocation_audio_urb -= 1;
-                                       m++;
-                               }
+                       if (pdata_urb && pdata_urb->purb) {
+                               usb_free_urb(pdata_urb->purb);
+                               pdata_urb->purb = NULL;
+                               peasycap->allocation_audio_urb--;
+                               m++;
                        }
                }
                JOM(4, "%i audio urbs freed\n", m);
@@ -851,7 +844,6 @@ static void easycap_delete(struct kref *pkref)
                                peasycap->allocation_audio_struct -=
                                                        sizeof(struct data_urb);
                                kfree(pdata_urb);
-                               pdata_urb = NULL;
                                m++;
                        }
                }
@@ -940,7 +932,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
                return -EFAULT;
        }
 /*---------------------------------------------------------------------------*/
-       kd = isdongle(peasycap);
+       kd = easycap_isdongle(peasycap);
        if (0 <= kd && DONGLE_MANY > kd) {
                if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
                        SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
@@ -952,7 +944,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
         *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
         *  IF NECESSARY, BAIL OUT.
         */
-               if (kd != isdongle(peasycap)) {
+               if (kd != easycap_isdongle(peasycap)) {
                        mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
                        return -ERESTARTSYS;
                }
@@ -980,21 +972,21 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
        */
                return -ERESTARTSYS;
 /*---------------------------------------------------------------------------*/
-       rc = easycap_dqbuf(peasycap, 0);
+       rc = easycap_video_dqbuf(peasycap, 0);
        peasycap->polled = 1;
        mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-       if (0 == rc)
-               return POLLIN | POLLRDNORM;
-       else
+       if (rc)
                return POLLERR;
-       }
+
+       return POLLIN | POLLRDNORM;
+}
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
  */
 /*---------------------------------------------------------------------------*/
-int easycap_dqbuf(struct easycap *peasycap, int mode)
+int easycap_video_dqbuf(struct easycap *peasycap, int mode)
 {
        int input, ifield, miss, rc;
 
@@ -1080,7 +1072,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
                                        JOM(8, " ... failed  returning -EIO\n");
                                        peasycap->video_eof = 1;
                                        peasycap->audio_eof = 1;
-                                       kill_video_urbs(peasycap);
+                                       easycap_video_kill_urbs(peasycap);
                                        return -EIO;
                                }
                                peasycap->status = 0;
@@ -1090,7 +1082,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
                        #endif /*PERSEVERE*/
                        peasycap->video_eof = 1;
                        peasycap->audio_eof = 1;
-                       kill_video_urbs(peasycap);
+                       easycap_video_kill_urbs(peasycap);
                        JOM(8, "returning -EIO\n");
                        return -EIO;
                }
@@ -1143,7 +1135,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
                                        JOM(8, " ... failed returning -EIO\n");
                                        peasycap->video_eof = 1;
                                        peasycap->audio_eof = 1;
-                                       kill_video_urbs(peasycap);
+                                       easycap_video_kill_urbs(peasycap);
                                        return -EIO;
                                }
                                peasycap->status = 0;
@@ -1153,7 +1145,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
 #endif /*PERSEVERE*/
                        peasycap->video_eof = 1;
                        peasycap->audio_eof = 1;
-                       kill_video_urbs(peasycap);
+                       easycap_video_kill_urbs(peasycap);
                        JOM(8, "returning -EIO\n");
                        return -EIO;
                }
@@ -1207,12 +1199,9 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
  *  WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
  *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
  *
- *  THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
- *  CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
  */
 /*---------------------------------------------------------------------------*/
-int
-field2frame(struct easycap *peasycap)
+static int field2frame(struct easycap *peasycap)
 {
 
        void *pex, *pad;
@@ -1221,7 +1210,7 @@ field2frame(struct easycap *peasycap)
        int rc, bytesperpixel, multiplier;
        int  much, more, over, rump, caches, input;
        u8 mask, margin;
-       bool odd, isuy, decimatepixel, offerfields, badinput;
+       bool odd, isuy, decimatepixel, badinput;
 
        if (!peasycap) {
                SAY("ERROR: peasycap is NULL\n");
@@ -1237,8 +1226,6 @@ field2frame(struct easycap *peasycap)
                        peasycap->field_buffer[peasycap->field_read][0].input,
                        peasycap->field_read, peasycap->frame_fill);
        JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
-       if (peasycap->offerfields)
-               JOM(8, "===== offerfields\n");
 
 /*---------------------------------------------------------------------------*/
 /*
@@ -1260,7 +1247,6 @@ field2frame(struct easycap *peasycap)
 #endif /*EASYCAP_TESTCARD*/
 /*---------------------------------------------------------------------------*/
 
-       offerfields = peasycap->offerfields;
        bytesperpixel = peasycap->bytesperpixel;
        decimatepixel = peasycap->decimatepixel;
 
@@ -1601,9 +1587,9 @@ field2frame(struct easycap *peasycap)
  *  REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-int
-redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
-                                       u8 mask, u8 margin, bool isuy)
+static int redaub(struct easycap *peasycap,
+               void *pad, void *pex, int much, int more,
+               u8 mask, u8 margin, bool isuy)
 {
        static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
        u8 *pcache;
@@ -2855,20 +2841,7 @@ static void easycap_complete(struct urb *purb)
        }
        return;
 }
-static const struct file_operations easycap_fops = {
-       .owner          = THIS_MODULE,
-       .open           = easycap_open,
-       .unlocked_ioctl = easycap_unlocked_ioctl,
-       .poll           = easycap_poll,
-       .mmap           = easycap_mmap,
-       .llseek         = no_llseek,
-};
-static const struct usb_class_driver easycap_class = {
-       .name = "usb/easycap%d",
-       .fops = &easycap_fops,
-       .minor_base = USB_SKEL_MINOR_BASE,
-};
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+
 static const struct v4l2_file_operations v4l2_fops = {
        .owner          = THIS_MODULE,
        .open           = easycap_open_noinode,
@@ -2917,6 +2890,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
                SAY("ERROR: usb_host_interface not found\n");
                return -EFAULT;
        }
+
        interface = &alt->desc;
        if (!interface) {
                SAY("ERROR: intf_descriptor is NULL\n");
@@ -2976,44 +2950,31 @@ static int easycap_usb_probe(struct usb_interface *intf,
                if (mutex_lock_interruptible(&mutex_dongle)) {
                        SAY("ERROR: cannot down mutex_dongle\n");
                        return -ERESTARTSYS;
-               } else {
-/*---------------------------------------------------------------------------*/
-               /*
-                *  FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
-                *  TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
-                *
-                *  NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
-                *  PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
-                *  EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
-               */
-/*---------------------------------------------------------------------------*/
-                       for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
-                               if ((!easycapdc60_dongle[ndong].peasycap) &&
-                                               (!mutex_is_locked(&easycapdc60_dongle
-                                                       [ndong].mutex_video)) &&
-                                               (!mutex_is_locked(&easycapdc60_dongle
-                                                       [ndong].mutex_audio))) {
-                                       easycapdc60_dongle[ndong].peasycap = peasycap;
-                                       peasycap->isdongle = ndong;
-                                       JOM(8, "intf[%i]: peasycap-->easycap"
-                                                       "_dongle[%i].peasycap\n",
-                                                       bInterfaceNumber, ndong);
-                                       break;
-                               }
-                       }
-                       if (DONGLE_MANY <= ndong) {
-                               SAM("ERROR: too many dongles\n");
-                               mutex_unlock(&mutex_dongle);
-                               return -ENOMEM;
+               }
+
+               for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+                       if ((!easycapdc60_dongle[ndong].peasycap) &&
+                                       (!mutex_is_locked(&easycapdc60_dongle
+                                               [ndong].mutex_video)) &&
+                                       (!mutex_is_locked(&easycapdc60_dongle
+                                               [ndong].mutex_audio))) {
+                               easycapdc60_dongle[ndong].peasycap = peasycap;
+                               peasycap->isdongle = ndong;
+                               JOM(8, "intf[%i]: peasycap-->easycap"
+                                               "_dongle[%i].peasycap\n",
+                                               bInterfaceNumber, ndong);
+                               break;
                        }
+               }
+
+               if (DONGLE_MANY <= ndong) {
+                       SAM("ERROR: too many dongles\n");
                        mutex_unlock(&mutex_dongle);
+                       return -ENOMEM;
                }
+               mutex_unlock(&mutex_dongle);
+
                peasycap->allocation_video_struct = sizeof(struct easycap);
-               peasycap->allocation_video_page = 0;
-               peasycap->allocation_video_urb = 0;
-               peasycap->allocation_audio_struct = 0;
-               peasycap->allocation_audio_page = 0;
-               peasycap->allocation_audio_urb = 0;
 
 /*---------------------------------------------------------------------------*/
 /*
@@ -3023,7 +2984,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
                peasycap->pusb_device = usbdev;
                peasycap->pusb_interface = intf;
 
-               peasycap->ilk = 0;
                peasycap->microphone = false;
 
                peasycap->video_interface = -1;
@@ -3042,38 +3002,21 @@ static int easycap_usb_probe(struct usb_interface *intf,
 
                peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
 
-               for (k = 0; k < INPUT_MANY; k++)
-                       peasycap->lost[k] = 0;
-               peasycap->skip = 0;
-               peasycap->skipped = 0;
-               peasycap->offerfields = 0;
 /*---------------------------------------------------------------------------*/
 /*
  *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
  */
 /*---------------------------------------------------------------------------*/
-               rc = fillin_formats();
+               rc = easycap_video_fillin_formats();
                if (0 > rc) {
                        SAM("ERROR: fillin_formats() rc = %i\n", rc);
                        return -EFAULT;
                }
                JOM(4, "%i formats available\n", rc);
-/*---------------------------------------------------------------------------*/
-/*
- *  ... AND POPULATE easycap.inputset[]
-*/
-/*---------------------------------------------------------------------------*/
-               /* FIXME: maybe we just use memset 0 */
+
+               /*  ... AND POPULATE easycap.inputset[] */
+
                inputset = peasycap->inputset;
-               for (k = 0; k < INPUT_MANY; k++) {
-                       inputset[k].input_ok = 0;
-                       inputset[k].standard_offset_ok = 0;
-                       inputset[k].format_offset_ok = 0;
-                       inputset[k].brightness_ok = 0;
-                       inputset[k].contrast_ok = 0;
-                       inputset[k].saturation_ok = 0;
-                       inputset[k].hue_ok = 0;
-               }
 
                fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
                m = 0;
@@ -3390,11 +3333,10 @@ static int easycap_usb_probe(struct usb_interface *intf,
                if (!isokalt) {
                        SAM("ERROR:  no viable video_altsetting_on\n");
                        return -ENOENT;
-               } else {
-                       peasycap->video_altsetting_on = okalt[isokalt - 1];
-                       JOM(4, "%i=video_altsetting_on <====\n",
-                                               peasycap->video_altsetting_on);
                }
+               peasycap->video_altsetting_on = okalt[isokalt - 1];
+               JOM(4, "%i=video_altsetting_on <====\n",
+                                       peasycap->video_altsetting_on);
 /*---------------------------------------------------------------------------*/
 /*
  *  DECIDE THE VIDEO STREAMING PARAMETERS
@@ -3480,8 +3422,9 @@ static int easycap_usb_probe(struct usb_interface *intf,
                                                SAM("ERROR: Could not allocate frame "
                                                        "buffer %i page %i\n", k, m);
                                                return -ENOMEM;
-                                       } else
-                                               peasycap->allocation_video_page += 1;
+                                       }
+
+                                       peasycap->allocation_video_page += 1;
                                        peasycap->frame_buffer[k][m].pgo = pbuf;
                                }
                                peasycap->frame_buffer[k][m].pto =
@@ -3510,11 +3453,11 @@ static int easycap_usb_probe(struct usb_interface *intf,
                                                SAM("ERROR: Could not allocate field"
                                                        " buffer %i page %i\n", k, m);
                                                return -ENOMEM;
-                                               }
-                                       else
-                                               peasycap->allocation_video_page += 1;
-                                       peasycap->field_buffer[k][m].pgo = pbuf;
                                        }
+
+                                       peasycap->allocation_video_page += 1;
+                                       peasycap->field_buffer[k][m].pgo = pbuf;
+                               }
                                peasycap->field_buffer[k][m].pto =
                                                peasycap->field_buffer[k][m].pgo;
                        }
@@ -3538,9 +3481,9 @@ static int easycap_usb_probe(struct usb_interface *intf,
                                SAM("ERROR: Could not allocate isoc video buffer "
                                                                        "%i\n", k);
                                return -ENOMEM;
-                       } else
-                               peasycap->allocation_video_page +=
-                                       BIT(VIDEO_ISOC_ORDER);
+                       }
+                       peasycap->allocation_video_page +=
+                                               BIT(VIDEO_ISOC_ORDER);
 
                        peasycap->video_isoc_buffer[k].pgo = pbuf;
                        peasycap->video_isoc_buffer[k].pto =
@@ -3569,15 +3512,17 @@ static int easycap_usb_probe(struct usb_interface *intf,
                                SAM("ERROR: usb_alloc_urb returned NULL for buffer "
                                                                        "%i\n", k);
                                return -ENOMEM;
-                       } else
-                               peasycap->allocation_video_urb += 1;
+                       }
+
+                       peasycap->allocation_video_urb += 1;
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
                        pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
                        if (!pdata_urb) {
                                SAM("ERROR: Could not allocate struct data_urb.\n");
                                return -ENOMEM;
-                       } else
-                               peasycap->allocation_video_struct +=
+                       }
+
+                       peasycap->allocation_video_struct +=
                                                        sizeof(struct data_urb);
 
                        pdata_urb->purb = purb;
@@ -3694,13 +3639,12 @@ static int easycap_usb_probe(struct usb_interface *intf,
                        err("Not able to register with videodev");
                        videodev_release(&(peasycap->video_device));
                        return -ENODEV;
-               } else {
-                       (peasycap->registered_video)++;
-                       SAM("registered with videodev: %i=minor\n",
-                                                       peasycap->video_device.minor);
-                       peasycap->minor = peasycap->video_device.minor;
                }
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
+               peasycap->registered_video++;
+               SAM("registered with videodev: %i=minor\n",
+                                               peasycap->video_device.minor);
+               peasycap->minor = peasycap->video_device.minor;
 
                break;
        }
@@ -3734,11 +3678,10 @@ static int easycap_usb_probe(struct usb_interface *intf,
                if (!isokalt) {
                        SAM("ERROR:  no viable audio_altsetting_on\n");
                        return -ENOENT;
-               } else {
-                       peasycap->audio_altsetting_on = okalt[isokalt - 1];
-                       JOM(4, "%i=audio_altsetting_on <====\n",
-                                                       peasycap->audio_altsetting_on);
                }
+               peasycap->audio_altsetting_on = okalt[isokalt - 1];
+               JOM(4, "%i=audio_altsetting_on <====\n",
+                                               peasycap->audio_altsetting_on);
 
                peasycap->audio_endpointnumber = okepn[isokalt - 1];
                JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
@@ -3847,8 +3790,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
                                SAM("ERROR: Could not allocate isoc audio buffer "
                                                                "%i\n", k);
                                return -ENOMEM;
-                       } else
-                               peasycap->allocation_audio_page +=
+                       }
+                       peasycap->allocation_audio_page +=
                                                BIT(AUDIO_ISOC_ORDER);
 
                        peasycap->audio_isoc_buffer[k].pgo = pbuf;
@@ -3996,12 +3939,9 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
 {
        struct usb_host_interface *pusb_host_interface;
        struct usb_interface_descriptor *pusb_interface_descriptor;
-       u8 bInterfaceNumber;
        struct easycap *peasycap;
-
-       struct list_head *plist_head;
-       struct data_urb *pdata_urb;
-       int minor, m, kd;
+       int minor, kd;
+       u8 bInterfaceNumber;
 
        JOT(4, "\n");
 
@@ -4036,45 +3976,14 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
        peasycap->audio_eof = 1;
        wake_up_interruptible(&(peasycap->wq_video));
        wake_up_interruptible(&(peasycap->wq_audio));
-/*---------------------------------------------------------------------------*/
+
        switch (bInterfaceNumber) {
-       case 0: {
-               if (peasycap->purb_video_head) {
-                       JOM(4, "killing video urbs\n");
-                       m = 0;
-                       list_for_each(plist_head, peasycap->purb_video_head) {
-                               pdata_urb = list_entry(plist_head,
-                                               struct data_urb, list_head);
-                               if (pdata_urb) {
-                                       if (pdata_urb->purb) {
-                                               usb_kill_urb(pdata_urb->purb);
-                                               m++;
-                                       }
-                               }
-                       }
-                       JOM(4, "%i video urbs killed\n", m);
-               }
+       case 0:
+               easycap_video_kill_urbs(peasycap);
                break;
-       }
-/*---------------------------------------------------------------------------*/
-       case 2: {
-               if (peasycap->purb_audio_head) {
-                       JOM(4, "killing audio urbs\n");
-                       m = 0;
-                       list_for_each(plist_head, peasycap->purb_audio_head) {
-                               pdata_urb = list_entry(plist_head,
-                                               struct data_urb, list_head);
-                               if (pdata_urb) {
-                                       if (pdata_urb->purb) {
-                                               usb_kill_urb(pdata_urb->purb);
-                                               m++;
-                                       }
-                               }
-                       }
-                       JOM(4, "%i audio urbs killed\n", m);
-               }
+       case 2:
+               easycap_audio_kill_urbs(peasycap);
                break;
-       }
        default:
                break;
        }
@@ -4087,7 +3996,7 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
  *  AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING.  BEWARE.
  */
 /*--------------------------------------------------------------------------*/
-       kd = isdongle(peasycap);
+       kd = easycap_isdongle(peasycap);
        switch (bInterfaceNumber) {
        case 0: {
                if (0 <= kd && DONGLE_MANY > kd) {
@@ -4212,7 +4121,7 @@ static struct usb_device_id easycap_usb_device_id_table[] = {
 };
 
 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
-struct usb_driver easycap_usb_driver = {
+static struct usb_driver easycap_usb_driver = {
        .name = "easycap",
        .id_table = easycap_usb_device_id_table,
        .probe = easycap_usb_probe,
index 70f59b13c34d7a1a5e5403e6b5ff2da22719f899..3f5f5b3e5a359b94f5839cc1f5ff1cde9d59d9c0 100644 (file)
@@ -313,7 +313,7 @@ const struct easycap_standard easycap_standard[] = {
 
 struct easycap_format easycap_format[1 + SETTINGS_MANY];
 
-int fillin_formats(void)
+int easycap_video_fillin_formats(void)
 {
        const char *name1, *name2, *name3, *name4;
        struct v4l2_format *fmt;
index b22bb39b5f69294882cdb82ca4b8f6c2b65f63c2..8c8bcae8ded8470886f81fac6599d88f67fb251c 100644 (file)
@@ -56,6 +56,141 @@ static const struct snd_pcm_hardware alsa_hardware = {
 };
 
 
+/*---------------------------------------------------------------------------*/
+/*
+ *  SUBMIT ALL AUDIO URBS.
+ */
+/*---------------------------------------------------------------------------*/
+static int easycap_audio_submit_urbs(struct easycap *peasycap)
+{
+       struct data_urb *pdata_urb;
+       struct urb *purb;
+       struct list_head *plist_head;
+       int j, isbad, nospc, m, rc;
+       int isbuf;
+
+       if (!peasycap->purb_audio_head) {
+               SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
+               return -EFAULT;
+       }
+       if (!peasycap->pusb_device) {
+               SAM("ERROR: peasycap->pusb_device is NULL\n");
+               return -EFAULT;
+       }
+
+       if (peasycap->audio_isoc_streaming) {
+               JOM(4, "already streaming audio urbs\n");
+               return 0;
+       }
+
+       JOM(4, "initial submission of all audio urbs\n");
+       rc = usb_set_interface(peasycap->pusb_device,
+                              peasycap->audio_interface,
+                              peasycap->audio_altsetting_on);
+       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
+           peasycap->audio_interface,
+           peasycap->audio_altsetting_on, rc);
+
+       isbad = 0;
+       nospc = 0;
+       m = 0;
+       list_for_each(plist_head, peasycap->purb_audio_head) {
+               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
+               if (pdata_urb && pdata_urb->purb) {
+                       purb = pdata_urb->purb;
+                       isbuf = pdata_urb->isbuf;
+
+                       purb->interval = 1;
+                       purb->dev = peasycap->pusb_device;
+                       purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
+                                       peasycap->audio_endpointnumber);
+                       purb->transfer_flags = URB_ISO_ASAP;
+                       purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
+                       purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
+                       purb->complete = easycap_alsa_complete;
+                       purb->context = peasycap;
+                       purb->start_frame = 0;
+                       purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
+                       for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
+                               purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
+                               purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
+                       }
+
+                       rc = usb_submit_urb(purb, GFP_KERNEL);
+                       if (rc) {
+                               isbad++;
+                               SAM("ERROR: usb_submit_urb() failed"
+                                   " for urb with rc: -%s: %d\n",
+                                   strerror(rc), rc);
+                       } else {
+                               m++;
+                       }
+               } else {
+                       isbad++;
+               }
+       }
+       if (nospc) {
+               SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
+               SAM(".....  possibly inadequate USB bandwidth\n");
+               peasycap->audio_eof = 1;
+       }
+
+       if (isbad)
+               easycap_audio_kill_urbs(peasycap);
+       else
+               peasycap->audio_isoc_streaming = m;
+
+       return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  COMMON AUDIO INITIALIZATION
+ */
+/*---------------------------------------------------------------------------*/
+static int easycap_sound_setup(struct easycap *peasycap)
+{
+       int rc;
+
+       JOM(4, "starting initialization\n");
+
+       if (!peasycap) {
+               SAY("ERROR:  peasycap is NULL.\n");
+               return -EFAULT;
+       }
+       if (!peasycap->pusb_device) {
+               SAM("ERROR: peasycap->pusb_device is NULL\n");
+               return -ENODEV;
+       }
+       JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
+
+       rc = easycap_audio_setup(peasycap);
+       JOM(8, "audio_setup() returned %i\n", rc);
+
+       if (!peasycap->pusb_device) {
+               SAM("ERROR: peasycap->pusb_device has become NULL\n");
+               return -ENODEV;
+       }
+/*---------------------------------------------------------------------------*/
+       if (!peasycap->pusb_device) {
+               SAM("ERROR: peasycap->pusb_device has become NULL\n");
+               return -ENODEV;
+       }
+       rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
+                              peasycap->audio_altsetting_on);
+       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
+           peasycap->audio_altsetting_on, rc);
+
+       rc = easycap_wakeup_device(peasycap->pusb_device);
+       JOM(8, "wakeup_device() returned %i\n", rc);
+
+       peasycap->audio_eof = 0;
+       peasycap->audio_idle = 0;
+
+       easycap_audio_submit_urbs(peasycap);
+
+       JOM(4, "finished initialization\n");
+       return 0;
+}
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
@@ -64,8 +199,7 @@ static const struct snd_pcm_hardware alsa_hardware = {
  *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
  */
 /*---------------------------------------------------------------------------*/
-void
-easycap_alsa_complete(struct urb *purb)
+void easycap_alsa_complete(struct urb *purb)
 {
        struct easycap *peasycap;
        struct snd_pcm_substream *pss;
@@ -458,7 +592,6 @@ static int easycap_alsa_ack(struct snd_pcm_substream *pss)
 static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
 {
        struct easycap *peasycap;
-       int retval;
 
        JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
            SNDRV_PCM_TRIGGER_STOP);
@@ -481,7 +614,7 @@ static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
                break;
        }
        default:
-               retval = -EINVAL;
+               return -EINVAL;
        }
        return 0;
 }
@@ -615,202 +748,3 @@ int easycap_alsa_probe(struct easycap *peasycap)
        return 0;
 }
 
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  COMMON AUDIO INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-int
-easycap_sound_setup(struct easycap *peasycap)
-{
-       int rc;
-
-       JOM(4, "starting initialization\n");
-
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL.\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -ENODEV;
-       }
-       JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
-
-       rc = audio_setup(peasycap);
-       JOM(8, "audio_setup() returned %i\n", rc);
-
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device has become NULL\n");
-               return -ENODEV;
-       }
-/*---------------------------------------------------------------------------*/
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device has become NULL\n");
-               return -ENODEV;
-       }
-       rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
-                              peasycap->audio_altsetting_on);
-       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
-           peasycap->audio_altsetting_on, rc);
-
-       rc = wakeup_device(peasycap->pusb_device);
-       JOM(8, "wakeup_device() returned %i\n", rc);
-
-       peasycap->audio_eof = 0;
-       peasycap->audio_idle = 0;
-
-       submit_audio_urbs(peasycap);
-
-       JOM(4, "finished initialization\n");
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  SUBMIT ALL AUDIO URBS.
- */
-/*---------------------------------------------------------------------------*/
-int
-submit_audio_urbs(struct easycap *peasycap)
-{
-       struct data_urb *pdata_urb;
-       struct urb *purb;
-       struct list_head *plist_head;
-       int j, isbad, nospc, m, rc;
-       int isbuf;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->purb_audio_head) {
-               SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-
-       if (peasycap->audio_isoc_streaming) {
-               JOM(4, "already streaming audio urbs\n");
-               return 0;
-       }
-
-       JOM(4, "initial submission of all audio urbs\n");
-       rc = usb_set_interface(peasycap->pusb_device,
-                              peasycap->audio_interface,
-                              peasycap->audio_altsetting_on);
-       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
-           peasycap->audio_interface,
-           peasycap->audio_altsetting_on, rc);
-
-       isbad = 0;
-       nospc = 0;
-       m = 0;
-       list_for_each(plist_head, peasycap->purb_audio_head) {
-               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-               if (pdata_urb && pdata_urb->purb) {
-                       purb = pdata_urb->purb;
-                       isbuf = pdata_urb->isbuf;
-
-                       purb->interval = 1;
-                       purb->dev = peasycap->pusb_device;
-                       purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
-                                       peasycap->audio_endpointnumber);
-                       purb->transfer_flags = URB_ISO_ASAP;
-                       purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
-                       purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
-                       purb->complete = easycap_alsa_complete;
-                       purb->context = peasycap;
-                       purb->start_frame = 0;
-                       purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
-                       for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
-                               purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
-                               purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
-                       }
-
-                       rc = usb_submit_urb(purb, GFP_KERNEL);
-                       if (rc) {
-                               isbad++;
-                               SAM("ERROR: usb_submit_urb() failed"
-                                   " for urb with rc: -%s: %d\n",
-                                   strerror(rc), rc);
-                       } else {
-                               m++;
-                       }
-               } else {
-                       isbad++;
-               }
-       }
-       if (nospc) {
-               SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
-               SAM(".....  possibly inadequate USB bandwidth\n");
-               peasycap->audio_eof = 1;
-       }
-       if (isbad) {
-               JOM(4, "attempting cleanup instead of submitting\n");
-               list_for_each(plist_head, (peasycap->purb_audio_head)) {
-                       pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-                       if (pdata_urb && pdata_urb->purb)
-                               usb_kill_urb(pdata_urb->purb);
-               }
-               peasycap->audio_isoc_streaming = 0;
-       } else {
-               peasycap->audio_isoc_streaming = m;
-               JOM(4, "submitted %i audio urbs\n", m);
-       }
-
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  KILL ALL AUDIO URBS.
- */
-/*---------------------------------------------------------------------------*/
-int
-kill_audio_urbs(struct easycap *peasycap)
-{
-       int m;
-       struct list_head *plist_head;
-       struct data_urb *pdata_urb;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-
-       if (!peasycap->audio_isoc_streaming) {
-               JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
-                   peasycap->audio_isoc_streaming);
-               return 0;
-       }
-
-       if (!peasycap->purb_audio_head) {
-               SAM("ERROR: peasycap->purb_audio_head is NULL\n");
-               return -EFAULT;
-       }
-
-       peasycap->audio_isoc_streaming = 0;
-       JOM(4, "killing audio urbs\n");
-       m = 0;
-       list_for_each(plist_head, (peasycap->purb_audio_head)) {
-               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-               if (pdata_urb && pdata_urb->purb) {
-                       usb_kill_urb(pdata_urb->purb);
-                       m++;
-               }
-       }
-       JOM(4, "%i audio urbs killed\n", m);
-
-       return 0;
-}
-/*****************************************************************************/
index b7175fe1b15f9c6331f16971cf0dbaf8e7681d3f..70e006b50f292259025b50a5b03a2aa26a9c2b5f 100644 (file)
@@ -1054,7 +1054,13 @@ static int go7007_usb_probe(struct usb_interface *intf,
        else
                go->hpi_ops = &go7007_usb_onboard_hpi_ops;
        go->hpi_context = usb;
-       usb_fill_int_urb(usb->intr_urb, usb->usbdev,
+       if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
+               usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
+                       usb_rcvbulkpipe(usb->usbdev, 4),
+                       usb->intr_urb->transfer_buffer, 2*sizeof(u16),
+                       go7007_usb_readinterrupt_complete, go);
+       else
+               usb_fill_int_urb(usb->intr_urb, usb->usbdev,
                        usb_rcvintpipe(usb->usbdev, 4),
                        usb->intr_urb->transfer_buffer, 2*sizeof(u16),
                        go7007_usb_readinterrupt_complete, go, 8);
index f68218012f231aab1f5fbe33953d140a8ff6a177..5f7f8cd3a66148bed7b5dfae551f6919d96c7454 100644 (file)
@@ -63,7 +63,7 @@ static int display_open(struct inode *inode, struct file *file);
 static int display_close(struct inode *inode, struct file *file);
 
 /* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
                         size_t n_bytes, loff_t *pos);
 
 /* LIRC driver function prototypes */
@@ -369,7 +369,7 @@ static int send_packet(struct imon_context *context)
  * than 32 bytes are provided spaces will be appended to
  * generate a full screen.
  */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
                         size_t n_bytes, loff_t *pos)
 {
        int i;
index 2aac67c98283a60757137e7f67dea2d7801d79ad..8dd8897ad86028da33ce68991fed3c302c4dcc2a 100644 (file)
@@ -773,7 +773,7 @@ static int hardware_init_port(void)
                /* we fail, there's nothing here */
                printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test "
                       "failed, cannot continue\n");
-               return -EINVAL;
+               return -ENODEV;
        }
 
 
@@ -836,25 +836,22 @@ static int hardware_init_port(void)
        return 0;
 }
 
-static int init_port(void)
+static int __devinit lirc_serial_probe(struct platform_device *dev)
 {
        int i, nlow, nhigh, result;
 
        result = request_irq(irq, irq_handler,
                             (share_irq ? IRQF_SHARED : 0),
                             LIRC_DRIVER_NAME, (void *)&hardware);
-
-       switch (result) {
-       case -EBUSY:
-               printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
-               return -EBUSY;
-       case -EINVAL:
-               printk(KERN_ERR LIRC_DRIVER_NAME
-                      ": Bad irq number or handler\n");
-               return -EINVAL;
-       default:
-               break;
-       };
+       if (result < 0) {
+               if (result == -EBUSY)
+                       printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n",
+                              irq);
+               else if (result == -EINVAL)
+                       printk(KERN_ERR LIRC_DRIVER_NAME
+                              ": Bad irq number or handler\n");
+               return result;
+       }
 
        /* Reserve io region. */
        /*
@@ -875,11 +872,13 @@ static int init_port(void)
                       ": or compile the serial port driver as module and\n");
                printk(KERN_WARNING LIRC_DRIVER_NAME
                       ": make sure this module is loaded first\n");
-               return -EBUSY;
+               result = -EBUSY;
+               goto exit_free_irq;
        }
 
-       if (hardware_init_port() < 0)
-               return -EINVAL;
+       result = hardware_init_port();
+       if (result < 0)
+               goto exit_release_region;
 
        /* Initialize pulse/space widths */
        init_timing_params(duty_cycle, freq);
@@ -911,6 +910,28 @@ static int init_port(void)
 
        dprintk("Interrupt %d, port %04x obtained\n", irq, io);
        return 0;
+
+exit_release_region:
+       if (iommap != 0)
+               release_mem_region(iommap, 8 << ioshift);
+       else
+               release_region(io, 8);
+exit_free_irq:
+       free_irq(irq, (void *)&hardware);
+
+       return result;
+}
+
+static int __devexit lirc_serial_remove(struct platform_device *dev)
+{
+       free_irq(irq, (void *)&hardware);
+
+       if (iommap != 0)
+               release_mem_region(iommap, 8 << ioshift);
+       else
+               release_region(io, 8);
+
+       return 0;
 }
 
 static int set_use_inc(void *data)
@@ -955,7 +976,7 @@ static ssize_t lirc_write(struct file *file, const char *buf,
        int *wbuf;
 
        if (!(hardware[type].features & LIRC_CAN_SEND_PULSE))
-               return -EBADF;
+               return -EPERM;
 
        count = n / sizeof(int);
        if (n % sizeof(int) || count % 2 == 0)
@@ -1006,11 +1027,11 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
                        return result;
                /* only LIRC_MODE_PULSE supported */
                if (value != LIRC_MODE_PULSE)
-                       return -ENOSYS;
+                       return -EINVAL;
                break;
 
        case LIRC_GET_LENGTH:
-               return -ENOSYS;
+               return -ENOIOCTLCMD;
                break;
 
        case LIRC_SET_SEND_DUTY_CYCLE:
@@ -1076,16 +1097,6 @@ static struct lirc_driver driver = {
 
 static struct platform_device *lirc_serial_dev;
 
-static int __devinit lirc_serial_probe(struct platform_device *dev)
-{
-       return 0;
-}
-
-static int __devexit lirc_serial_remove(struct platform_device *dev)
-{
-       return 0;
-}
-
 static int lirc_serial_suspend(struct platform_device *dev,
                               pm_message_t state)
 {
@@ -1111,11 +1122,11 @@ static void lirc_serial_exit(void);
 static int lirc_serial_resume(struct platform_device *dev)
 {
        unsigned long flags;
+       int result;
 
-       if (hardware_init_port() < 0) {
-               lirc_serial_exit();
-               return -EINVAL;
-       }
+       result = hardware_init_port();
+       if (result < 0)
+               return result;
 
        spin_lock_irqsave(&hardware[type].lock, flags);
        /* Enable Interrupt */
@@ -1148,7 +1159,7 @@ static int __init lirc_serial_init(void)
        /* Init read buffer. */
        result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
        if (result < 0)
-               return -ENOMEM;
+               return result;
 
        result = platform_driver_register(&lirc_serial_driver);
        if (result) {
@@ -1188,10 +1199,6 @@ static int __init lirc_serial_init_module(void)
 {
        int result;
 
-       result = lirc_serial_init();
-       if (result)
-               return result;
-
        switch (type) {
        case LIRC_HOMEBREW:
        case LIRC_IRDEO:
@@ -1211,8 +1218,7 @@ static int __init lirc_serial_init_module(void)
                break;
 #endif
        default:
-               result = -EINVAL;
-               goto exit_serial_exit;
+               return -EINVAL;
        }
        if (!softcarrier) {
                switch (type) {
@@ -1228,37 +1234,26 @@ static int __init lirc_serial_init_module(void)
                }
        }
 
-       result = init_port();
-       if (result < 0)
-               goto exit_serial_exit;
+       result = lirc_serial_init();
+       if (result)
+               return result;
+
        driver.features = hardware[type].features;
        driver.dev = &lirc_serial_dev->dev;
        driver.minor = lirc_register_driver(&driver);
        if (driver.minor < 0) {
                printk(KERN_ERR  LIRC_DRIVER_NAME
                       ": register_chrdev failed!\n");
-               result = -EIO;
-               goto exit_release;
+               lirc_serial_exit();
+               return driver.minor;
        }
        return 0;
-exit_release:
-       release_region(io, 8);
-exit_serial_exit:
-       lirc_serial_exit();
-       return result;
 }
 
 static void __exit lirc_serial_exit_module(void)
 {
-       lirc_serial_exit();
-
-       free_irq(irq, (void *)&hardware);
-
-       if (iommap != 0)
-               release_mem_region(iommap, 8 << ioshift);
-       else
-               release_region(io, 8);
        lirc_unregister_driver(driver.minor);
+       lirc_serial_exit();
        dprintk("cleaned up module\n");
 }
 
index 72816cf167041afaac21099f47005eca975d2019..337e38c3a0f02c85904cbd9e4fd51525c8d1f34d 100644 (file)
@@ -1,3 +1,3 @@
 solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o
 
-obj-$(CONFIG_SOLO6X10) := solo6x10.o
+obj-$(CONFIG_SOLO6X10) += solo6x10.o
diff --git a/drivers/staging/media/solo6x10/jpeg.h b/drivers/staging/media/solo6x10/jpeg.h
deleted file mode 100644 (file)
index 50defec..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
- * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SOLO6X10_JPEG_H
-#define __SOLO6X10_JPEG_H
-
-static unsigned char jpeg_header[] = {
-       0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
-       0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
-       0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
-       0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c,
-       0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30,
-       0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50,
-       0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e,
-       0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a,
-       0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4,
-       0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0,
-       0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb,
-       0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a,
-       0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70,
-       0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-       0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00,
-       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-       0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
-       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-       0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
-       0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
-       0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
-       0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
-       0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
-       0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
-       0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
-       0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-       0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
-       0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
-       0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
-       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
-       0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
-       0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-       0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
-       0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-       0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
-       0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
-       0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
-       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-       0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
-       0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
-       0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
-       0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
-       0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
-       0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
-       0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
-       0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
-       0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
-       0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
-       0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
-       0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
-       0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
-       0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
-       0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
-       0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-       0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
-       0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-       0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
-       0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
-       0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
-       0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
-       0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
-       0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
-       0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
-       0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
-       0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-};
-
-/* This is the byte marker for the start of SOF0: 0xffc0 marker */
-#define SOF0_START     575
-
-#endif /* __SOLO6X10_JPEG_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
new file mode 100644 (file)
index 0000000..50defec
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
+ * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SOLO6X10_JPEG_H
+#define __SOLO6X10_JPEG_H
+
+static unsigned char jpeg_header[] = {
+       0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
+       0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
+       0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
+       0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c,
+       0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30,
+       0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50,
+       0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e,
+       0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a,
+       0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4,
+       0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0,
+       0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb,
+       0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a,
+       0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70,
+       0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+       0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00,
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
+       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+       0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
+       0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
+       0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
+       0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
+       0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+       0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
+       0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
+       0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+       0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
+       0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
+       0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
+       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
+       0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+       0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+       0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+       0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+       0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
+       0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+       0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
+       0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
+       0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
+       0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
+       0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
+       0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
+       0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
+       0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
+       0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
+       0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
+       0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
+       0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
+       0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
+       0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
+       0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
+       0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+       0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+       0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+       0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
+       0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
+       0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
+       0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
+       0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
+       0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
+       0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
+       0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+};
+
+/* This is the byte marker for the start of SOF0: 0xffc0 marker */
+#define SOF0_START     575
+
+#endif /* __SOLO6X10_JPEG_H */
index bee7280bbed985c59b4e919f229e22834d4aced7..f8f0da952288d127963bdd3c19887864c141f494 100644 (file)
@@ -26,7 +26,7 @@
 #include <media/videobuf-dma-sg.h>
 #include "solo6x10.h"
 #include "tw28.h"
-#include "jpeg.h"
+#include "solo6x10-jpeg.h"
 
 #define MIN_VID_BUFFERS                4
 #define FRAME_BUF_SIZE         (128 * 1024)
index 32793ce3d9e9dd4a32588204d5a59680046374e6..9c2cc4633894b152047ed587b2cf9494d5fdc684 100644 (file)
@@ -183,7 +183,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
        }
 
        irq = irq_of_parse_and_map(dn, 0);
-       if (irq == NO_IRQ) {
+       if (!irq) {
                printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
                rv = -EBUSY;
                goto err_irq;
index 3832e303c33aca5ceabf0bb1540e02a28b7765bc..596e6a7b17d68bc3ebf424cc11344da1cc32f1e5 100644 (file)
@@ -221,7 +221,7 @@ static int register_balloon(struct device *dev)
 {
        int i, error;
 
-       error = bus_register(&balloon_subsys);
+       error = subsys_system_register(&balloon_subsys, NULL);
        if (error)
                return error;
 
index a10e428b32b4a62dfc22d515d29c423b7e130a01..a26bea10e81bae5c9ee1890102ce86b7929bde28 100644 (file)
 
 #include <linux/hiddev.h>
 
+#define __DVB_CORE__
 #include <linux/dvb/audio.h>
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
index 281ae95932c923f3df37fbe8df53b10509974ef4..48cfac31f64ce2b3679362b91f324ff9afc4e262 100644 (file)
@@ -90,9 +90,9 @@ static int is_writable(struct pnfs_block_extent *be, sector_t isect)
  */
 struct parallel_io {
        struct kref refcnt;
-       struct rpc_call_ops call_ops;
-       void (*pnfs_callback) (void *data);
+       void (*pnfs_callback) (void *data, int num_se);
        void *data;
+       int bse_count;
 };
 
 static inline struct parallel_io *alloc_parallel(void *data)
@@ -103,6 +103,7 @@ static inline struct parallel_io *alloc_parallel(void *data)
        if (rv) {
                rv->data = data;
                kref_init(&rv->refcnt);
+               rv->bse_count = 0;
        }
        return rv;
 }
@@ -117,7 +118,7 @@ static void destroy_parallel(struct kref *kref)
        struct parallel_io *p = container_of(kref, struct parallel_io, refcnt);
 
        dprintk("%s enter\n", __func__);
-       p->pnfs_callback(p->data);
+       p->pnfs_callback(p->data, p->bse_count);
        kfree(p);
 }
 
@@ -146,14 +147,19 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
 {
        struct bio *bio;
 
+       npg = min(npg, BIO_MAX_PAGES);
        bio = bio_alloc(GFP_NOIO, npg);
-       if (!bio)
-               return NULL;
+       if (!bio && (current->flags & PF_MEMALLOC)) {
+               while (!bio && (npg /= 2))
+                       bio = bio_alloc(GFP_NOIO, npg);
+       }
 
-       bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
-       bio->bi_bdev = be->be_mdev;
-       bio->bi_end_io = end_io;
-       bio->bi_private = par;
+       if (bio) {
+               bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+               bio->bi_bdev = be->be_mdev;
+               bio->bi_end_io = end_io;
+               bio->bi_private = par;
+       }
        return bio;
 }
 
@@ -212,22 +218,15 @@ static void bl_read_cleanup(struct work_struct *work)
 }
 
 static void
-bl_end_par_io_read(void *data)
+bl_end_par_io_read(void *data, int unused)
 {
        struct nfs_read_data *rdata = data;
 
+       rdata->task.tk_status = rdata->pnfs_error;
        INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup);
        schedule_work(&rdata->task.u.tk_work);
 }
 
-/* We don't want normal .rpc_call_done callback used, so we replace it
- * with this stub.
- */
-static void bl_rpc_do_nothing(struct rpc_task *task, void *calldata)
-{
-       return;
-}
-
 static enum pnfs_try_status
 bl_read_pagelist(struct nfs_read_data *rdata)
 {
@@ -247,8 +246,6 @@ bl_read_pagelist(struct nfs_read_data *rdata)
        par = alloc_parallel(rdata);
        if (!par)
                goto use_mds;
-       par->call_ops = *rdata->mds_ops;
-       par->call_ops.rpc_call_done = bl_rpc_do_nothing;
        par->pnfs_callback = bl_end_par_io_read;
        /* At this point, we can no longer jump to use_mds */
 
@@ -322,6 +319,7 @@ static void mark_extents_written(struct pnfs_block_layout *bl,
 {
        sector_t isect, end;
        struct pnfs_block_extent *be;
+       struct pnfs_block_short_extent *se;
 
        dprintk("%s(%llu, %u)\n", __func__, offset, count);
        if (count == 0)
@@ -334,8 +332,11 @@ static void mark_extents_written(struct pnfs_block_layout *bl,
                be = bl_find_get_extent(bl, isect, NULL);
                BUG_ON(!be); /* FIXME */
                len = min(end, be->be_f_offset + be->be_length) - isect;
-               if (be->be_state == PNFS_BLOCK_INVALID_DATA)
-                       bl_mark_for_commit(be, isect, len); /* What if fails? */
+               if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+                       se = bl_pop_one_short_extent(be->be_inval);
+                       BUG_ON(!se);
+                       bl_mark_for_commit(be, isect, len, se);
+               }
                isect += len;
                bl_put_extent(be);
        }
@@ -357,7 +358,8 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
                end_page_writeback(page);
                page_cache_release(page);
        } while (bvec >= bio->bi_io_vec);
-       if (!uptodate) {
+
+       if (unlikely(!uptodate)) {
                if (!wdata->pnfs_error)
                        wdata->pnfs_error = -EIO;
                pnfs_set_lo_fail(wdata->lseg);
@@ -366,7 +368,6 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
        put_parallel(par);
 }
 
-/* This is basically copied from mpage_end_io_read */
 static void bl_end_io_write(struct bio *bio, int err)
 {
        struct parallel_io *par = bio->bi_private;
@@ -392,7 +393,7 @@ static void bl_write_cleanup(struct work_struct *work)
        dprintk("%s enter\n", __func__);
        task = container_of(work, struct rpc_task, u.tk_work);
        wdata = container_of(task, struct nfs_write_data, task);
-       if (!wdata->pnfs_error) {
+       if (likely(!wdata->pnfs_error)) {
                /* Marks for LAYOUTCOMMIT */
                mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
                                     wdata->args.offset, wdata->args.count);
@@ -401,11 +402,16 @@ static void bl_write_cleanup(struct work_struct *work)
 }
 
 /* Called when last of bios associated with a bl_write_pagelist call finishes */
-static void bl_end_par_io_write(void *data)
+static void bl_end_par_io_write(void *data, int num_se)
 {
        struct nfs_write_data *wdata = data;
 
-       wdata->task.tk_status = 0;
+       if (unlikely(wdata->pnfs_error)) {
+               bl_free_short_extents(&BLK_LSEG2EXT(wdata->lseg)->bl_inval,
+                                       num_se);
+       }
+
+       wdata->task.tk_status = wdata->pnfs_error;
        wdata->verf.committed = NFS_FILE_SYNC;
        INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup);
        schedule_work(&wdata->task.u.tk_work);
@@ -484,6 +490,55 @@ cleanup:
        return ret;
 }
 
+/* Find or create a zeroing page marked being writeback.
+ * Return ERR_PTR on error, NULL to indicate skip this page and page itself
+ * to indicate write out.
+ */
+static struct page *
+bl_find_get_zeroing_page(struct inode *inode, pgoff_t index,
+                       struct pnfs_block_extent *cow_read)
+{
+       struct page *page;
+       int locked = 0;
+       page = find_get_page(inode->i_mapping, index);
+       if (page)
+               goto check_page;
+
+       page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
+       if (unlikely(!page)) {
+               dprintk("%s oom\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+       locked = 1;
+
+check_page:
+       /* PageDirty: Other will write this out
+        * PageWriteback: Other is writing this out
+        * PageUptodate: It was read before
+        */
+       if (PageDirty(page) || PageWriteback(page)) {
+               print_page(page);
+               if (locked)
+                       unlock_page(page);
+               page_cache_release(page);
+               return NULL;
+       }
+
+       if (!locked) {
+               lock_page(page);
+               locked = 1;
+               goto check_page;
+       }
+       if (!PageUptodate(page)) {
+               /* New page, readin or zero it */
+               init_page_for_write(page, cow_read);
+       }
+       set_page_writeback(page);
+       unlock_page(page);
+
+       return page;
+}
+
 static enum pnfs_try_status
 bl_write_pagelist(struct nfs_write_data *wdata, int sync)
 {
@@ -508,9 +563,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
         */
        par = alloc_parallel(wdata);
        if (!par)
-               return PNFS_NOT_ATTEMPTED;
-       par->call_ops = *wdata->mds_ops;
-       par->call_ops.rpc_call_done = bl_rpc_do_nothing;
+               goto out_mds;
        par->pnfs_callback = bl_end_par_io_write;
        /* At this point, have to be more careful with error handling */
 
@@ -518,12 +571,15 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
        be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), isect, &cow_read);
        if (!be || !is_writable(be, isect)) {
                dprintk("%s no matching extents!\n", __func__);
-               wdata->pnfs_error = -EINVAL;
-               goto out;
+               goto out_mds;
        }
 
        /* First page inside INVALID extent */
        if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+               if (likely(!bl_push_one_short_extent(be->be_inval)))
+                       par->bse_count++;
+               else
+                       goto out_mds;
                temp = offset >> PAGE_CACHE_SHIFT;
                npg_zero = do_div(temp, npg_per_block);
                isect = (sector_t) (((offset - npg_zero * PAGE_CACHE_SIZE) &
@@ -543,36 +599,16 @@ fill_invalid_ext:
                        dprintk("%s zero %dth page: index %lu isect %llu\n",
                                __func__, npg_zero, index,
                                (unsigned long long)isect);
-                       page =
-                           find_or_create_page(wdata->inode->i_mapping, index,
-                                               GFP_NOFS);
-                       if (!page) {
-                               dprintk("%s oom\n", __func__);
-                               wdata->pnfs_error = -ENOMEM;
+                       page = bl_find_get_zeroing_page(wdata->inode, index,
+                                                       cow_read);
+                       if (unlikely(IS_ERR(page))) {
+                               wdata->pnfs_error = PTR_ERR(page);
                                goto out;
-                       }
-
-                       /* PageDirty: Other will write this out
-                        * PageWriteback: Other is writing this out
-                        * PageUptodate: It was read before
-                        * sector_initialized: already written out
-                        */
-                       if (PageDirty(page) || PageWriteback(page)) {
-                               print_page(page);
-                               unlock_page(page);
-                               page_cache_release(page);
+                       } else if (page == NULL)
                                goto next_page;
-                       }
-                       if (!PageUptodate(page)) {
-                               /* New page, readin or zero it */
-                               init_page_for_write(page, cow_read);
-                       }
-                       set_page_writeback(page);
-                       unlock_page(page);
 
                        ret = bl_mark_sectors_init(be->be_inval, isect,
-                                                      PAGE_CACHE_SECTORS,
-                                                      NULL);
+                                                      PAGE_CACHE_SECTORS);
                        if (unlikely(ret)) {
                                dprintk("%s bl_mark_sectors_init fail %d\n",
                                        __func__, ret);
@@ -581,6 +617,19 @@ fill_invalid_ext:
                                wdata->pnfs_error = ret;
                                goto out;
                        }
+                       if (likely(!bl_push_one_short_extent(be->be_inval)))
+                               par->bse_count++;
+                       else {
+                               end_page_writeback(page);
+                               page_cache_release(page);
+                               wdata->pnfs_error = -ENOMEM;
+                               goto out;
+                       }
+                       /* FIXME: This should be done in bi_end_io */
+                       mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
+                                            page->index << PAGE_CACHE_SHIFT,
+                                            PAGE_CACHE_SIZE);
+
                        bio = bl_add_page_to_bio(bio, npg_zero, WRITE,
                                                 isect, page, be,
                                                 bl_end_io_write_zero, par);
@@ -589,10 +638,6 @@ fill_invalid_ext:
                                bio = NULL;
                                goto out;
                        }
-                       /* FIXME: This should be done in bi_end_io */
-                       mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
-                                            page->index << PAGE_CACHE_SHIFT,
-                                            PAGE_CACHE_SIZE);
 next_page:
                        isect += PAGE_CACHE_SECTORS;
                        extent_length -= PAGE_CACHE_SECTORS;
@@ -616,13 +661,21 @@ next_page:
                                wdata->pnfs_error = -EINVAL;
                                goto out;
                        }
+                       if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
+                               if (likely(!bl_push_one_short_extent(
+                                                               be->be_inval)))
+                                       par->bse_count++;
+                               else {
+                                       wdata->pnfs_error = -ENOMEM;
+                                       goto out;
+                               }
+                       }
                        extent_length = be->be_length -
                            (isect - be->be_f_offset);
                }
                if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
                        ret = bl_mark_sectors_init(be->be_inval, isect,
-                                                      PAGE_CACHE_SECTORS,
-                                                      NULL);
+                                                      PAGE_CACHE_SECTORS);
                        if (unlikely(ret)) {
                                dprintk("%s bl_mark_sectors_init fail %d\n",
                                        __func__, ret);
@@ -664,6 +717,10 @@ out:
        bl_submit_bio(WRITE, bio);
        put_parallel(par);
        return PNFS_ATTEMPTED;
+out_mds:
+       bl_put_extent(be);
+       kfree(par);
+       return PNFS_NOT_ATTEMPTED;
 }
 
 /* FIXME - range ignored */
@@ -690,11 +747,17 @@ static void
 release_inval_marks(struct pnfs_inval_markings *marks)
 {
        struct pnfs_inval_tracking *pos, *temp;
+       struct pnfs_block_short_extent *se, *stemp;
 
        list_for_each_entry_safe(pos, temp, &marks->im_tree.mtt_stub, it_link) {
                list_del(&pos->it_link);
                kfree(pos);
        }
+
+       list_for_each_entry_safe(se, stemp, &marks->im_extents, bse_node) {
+               list_del(&se->bse_node);
+               kfree(se);
+       }
        return;
 }
 
@@ -779,16 +842,13 @@ bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
 static void free_blk_mountid(struct block_mount_id *mid)
 {
        if (mid) {
-               struct pnfs_block_dev *dev;
-               spin_lock(&mid->bm_lock);
-               while (!list_empty(&mid->bm_devlist)) {
-                       dev = list_first_entry(&mid->bm_devlist,
-                                              struct pnfs_block_dev,
-                                              bm_node);
+               struct pnfs_block_dev *dev, *tmp;
+
+               /* No need to take bm_lock as we are last user freeing bm_devlist */
+               list_for_each_entry_safe(dev, tmp, &mid->bm_devlist, bm_node) {
                        list_del(&dev->bm_node);
                        bl_free_block_dev(dev);
                }
-               spin_unlock(&mid->bm_lock);
                kfree(mid);
        }
 }
index 42acf7ef59926d61ce0b4a12e208585d928a9aad..e31a2df28e70aca040560b8d94403d85d67cd170 100644 (file)
@@ -70,6 +70,7 @@ struct pnfs_inval_markings {
        spinlock_t      im_lock;
        struct my_tree  im_tree;        /* Sectors that need LAYOUTCOMMIT */
        sector_t        im_block_size;  /* Server blocksize in sectors */
+       struct list_head im_extents;    /* Short extents for INVAL->RW conversion */
 };
 
 struct pnfs_inval_tracking {
@@ -105,6 +106,7 @@ BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
 {
        spin_lock_init(&marks->im_lock);
        INIT_LIST_HEAD(&marks->im_tree.mtt_stub);
+       INIT_LIST_HEAD(&marks->im_extents);
        marks->im_block_size = blocksize;
        marks->im_tree.mtt_step_size = min((sector_t)PAGE_CACHE_SECTORS,
                                           blocksize);
@@ -186,8 +188,7 @@ struct pnfs_block_extent *
 bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
                struct pnfs_block_extent **cow_read);
 int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
-                            sector_t offset, sector_t length,
-                            sector_t **pages);
+                            sector_t offset, sector_t length);
 void bl_put_extent(struct pnfs_block_extent *be);
 struct pnfs_block_extent *bl_alloc_extent(void);
 int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
@@ -200,6 +201,11 @@ void clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
 int bl_add_merge_extent(struct pnfs_block_layout *bl,
                         struct pnfs_block_extent *new);
 int bl_mark_for_commit(struct pnfs_block_extent *be,
-                       sector_t offset, sector_t length);
+                       sector_t offset, sector_t length,
+                       struct pnfs_block_short_extent *new);
+int bl_push_one_short_extent(struct pnfs_inval_markings *marks);
+struct pnfs_block_short_extent *
+bl_pop_one_short_extent(struct pnfs_inval_markings *marks);
+void bl_free_short_extents(struct pnfs_inval_markings *marks, int num_to_free);
 
 #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
index 19fa7b0b8c00d8d2fdebef8b25e59a1b5b0598de..1abac09f7cd5f9fd46cc07401873067e49a4b7f7 100644 (file)
@@ -110,13 +110,7 @@ static int _add_entry(struct my_tree *tree, u64 s, int32_t tag,
                return 0;
        } else {
                struct pnfs_inval_tracking *new;
-               if (storage)
-                       new = storage;
-               else {
-                       new = kmalloc(sizeof(*new), GFP_NOFS);
-                       if (!new)
-                               return -ENOMEM;
-               }
+               new = storage;
                new->it_sector = s;
                new->it_tags = (1 << tag);
                list_add(&new->it_link, &pos->it_link);
@@ -139,11 +133,13 @@ static int _set_range(struct my_tree *tree, int32_t tag, u64 s, u64 length)
 }
 
 /* Ensure that future operations on given range of tree will not malloc */
-static int _preload_range(struct my_tree *tree, u64 offset, u64 length)
+static int _preload_range(struct pnfs_inval_markings *marks,
+               u64 offset, u64 length)
 {
        u64 start, end, s;
        int count, i, used = 0, status = -ENOMEM;
        struct pnfs_inval_tracking **storage;
+       struct my_tree  *tree = &marks->im_tree;
 
        dprintk("%s(%llu, %llu) enter\n", __func__, offset, length);
        start = normalize(offset, tree->mtt_step_size);
@@ -161,12 +157,11 @@ static int _preload_range(struct my_tree *tree, u64 offset, u64 length)
                        goto out_cleanup;
        }
 
-       /* Now need lock - HOW??? */
-
+       spin_lock_bh(&marks->im_lock);
        for (s = start; s < end; s += tree->mtt_step_size)
                used += _add_entry(tree, s, INTERNAL_EXISTS, storage[used]);
+       spin_unlock_bh(&marks->im_lock);
 
-       /* Unlock - HOW??? */
        status = 0;
 
  out_cleanup:
@@ -179,41 +174,14 @@ static int _preload_range(struct my_tree *tree, u64 offset, u64 length)
        return status;
 }
 
-static void set_needs_init(sector_t *array, sector_t offset)
-{
-       sector_t *p = array;
-
-       dprintk("%s enter\n", __func__);
-       if (!p)
-               return;
-       while (*p < offset)
-               p++;
-       if (*p == offset)
-               return;
-       else if (*p == ~0) {
-               *p++ = offset;
-               *p = ~0;
-               return;
-       } else {
-               sector_t *save = p;
-               dprintk("%s Adding %llu\n", __func__, (u64)offset);
-               while (*p != ~0)
-                       p++;
-               p++;
-               memmove(save + 1, save, (char *)p - (char *)save);
-               *save = offset;
-               return;
-       }
-}
-
 /* We are relying on page lock to serialize this */
 int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect)
 {
        int rv;
 
-       spin_lock(&marks->im_lock);
+       spin_lock_bh(&marks->im_lock);
        rv = _has_tag(&marks->im_tree, isect, EXTENT_INITIALIZED);
-       spin_unlock(&marks->im_lock);
+       spin_unlock_bh(&marks->im_lock);
        return rv;
 }
 
@@ -253,78 +221,39 @@ static int is_range_written(struct pnfs_inval_markings *marks,
 {
        int rv;
 
-       spin_lock(&marks->im_lock);
+       spin_lock_bh(&marks->im_lock);
        rv = _range_has_tag(&marks->im_tree, start, end, EXTENT_WRITTEN);
-       spin_unlock(&marks->im_lock);
+       spin_unlock_bh(&marks->im_lock);
        return rv;
 }
 
 /* Marks sectors in [offest, offset_length) as having been initialized.
  * All lengths are step-aligned, where step is min(pagesize, blocksize).
- * Notes where partial block is initialized, and helps prepare it for
- * complete initialization later.
+ * Currently assumes offset is page-aligned
  */
-/* Currently assumes offset is page-aligned */
 int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
-                            sector_t offset, sector_t length,
-                            sector_t **pages)
+                            sector_t offset, sector_t length)
 {
-       sector_t s, start, end;
-       sector_t *array = NULL; /* Pages to mark */
+       sector_t start, end;
 
        dprintk("%s(offset=%llu,len=%llu) enter\n",
                __func__, (u64)offset, (u64)length);
-       s = max((sector_t) 3,
-               2 * (marks->im_block_size / (PAGE_CACHE_SECTORS)));
-       dprintk("%s set max=%llu\n", __func__, (u64)s);
-       if (pages) {
-               array = kmalloc(s * sizeof(sector_t), GFP_NOFS);
-               if (!array)
-                       goto outerr;
-               array[0] = ~0;
-       }
 
        start = normalize(offset, marks->im_block_size);
        end = normalize_up(offset + length, marks->im_block_size);
-       if (_preload_range(&marks->im_tree, start, end - start))
+       if (_preload_range(marks, start, end - start))
                goto outerr;
 
-       spin_lock(&marks->im_lock);
-
-       for (s = normalize_up(start, PAGE_CACHE_SECTORS);
-            s < offset; s += PAGE_CACHE_SECTORS) {
-               dprintk("%s pre-area pages\n", __func__);
-               /* Portion of used block is not initialized */
-               if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
-                       set_needs_init(array, s);
-       }
+       spin_lock_bh(&marks->im_lock);
        if (_set_range(&marks->im_tree, EXTENT_INITIALIZED, offset, length))
                goto out_unlock;
-       for (s = normalize_up(offset + length, PAGE_CACHE_SECTORS);
-            s < end; s += PAGE_CACHE_SECTORS) {
-               dprintk("%s post-area pages\n", __func__);
-               if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
-                       set_needs_init(array, s);
-       }
-
-       spin_unlock(&marks->im_lock);
+       spin_unlock_bh(&marks->im_lock);
 
-       if (pages) {
-               if (array[0] == ~0) {
-                       kfree(array);
-                       *pages = NULL;
-               } else
-                       *pages = array;
-       }
        return 0;
 
- out_unlock:
-       spin_unlock(&marks->im_lock);
- outerr:
-       if (pages) {
-               kfree(array);
-               *pages = NULL;
-       }
+out_unlock:
+       spin_unlock_bh(&marks->im_lock);
+outerr:
        return -ENOMEM;
 }
 
@@ -338,9 +267,9 @@ static int mark_written_sectors(struct pnfs_inval_markings *marks,
 
        dprintk("%s(offset=%llu,len=%llu) enter\n", __func__,
                (u64)offset, (u64)length);
-       spin_lock(&marks->im_lock);
+       spin_lock_bh(&marks->im_lock);
        status = _set_range(&marks->im_tree, EXTENT_WRITTEN, offset, length);
-       spin_unlock(&marks->im_lock);
+       spin_unlock_bh(&marks->im_lock);
        return status;
 }
 
@@ -440,20 +369,18 @@ static void add_to_commitlist(struct pnfs_block_layout *bl,
 
 /* Note the range described by offset, length is guaranteed to be contained
  * within be.
+ * new will be freed, either by this function or add_to_commitlist if they
+ * decide not to use it, or after LAYOUTCOMMIT uses it in the commitlist.
  */
 int bl_mark_for_commit(struct pnfs_block_extent *be,
-                   sector_t offset, sector_t length)
+                   sector_t offset, sector_t length,
+                   struct pnfs_block_short_extent *new)
 {
        sector_t new_end, end = offset + length;
-       struct pnfs_block_short_extent *new;
        struct pnfs_block_layout *bl = container_of(be->be_inval,
                                                    struct pnfs_block_layout,
                                                    bl_inval);
 
-       new = kmalloc(sizeof(*new), GFP_NOFS);
-       if (!new)
-               return -ENOMEM;
-
        mark_written_sectors(be->be_inval, offset, length);
        /* We want to add the range to commit list, but it must be
         * block-normalized, and verified that the normalized range has
@@ -483,9 +410,6 @@ int bl_mark_for_commit(struct pnfs_block_extent *be,
        new->bse_mdev = be->be_mdev;
 
        spin_lock(&bl->bl_ext_lock);
-       /* new will be freed, either by add_to_commitlist if it decides not
-        * to use it, or after LAYOUTCOMMIT uses it in the commitlist.
-        */
        add_to_commitlist(bl, new);
        spin_unlock(&bl->bl_ext_lock);
        return 0;
@@ -933,3 +857,53 @@ clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
                }
        }
 }
+
+int bl_push_one_short_extent(struct pnfs_inval_markings *marks)
+{
+       struct pnfs_block_short_extent *new;
+
+       new = kmalloc(sizeof(*new), GFP_NOFS);
+       if (unlikely(!new))
+               return -ENOMEM;
+
+       spin_lock_bh(&marks->im_lock);
+       list_add(&new->bse_node, &marks->im_extents);
+       spin_unlock_bh(&marks->im_lock);
+
+       return 0;
+}
+
+struct pnfs_block_short_extent *
+bl_pop_one_short_extent(struct pnfs_inval_markings *marks)
+{
+       struct pnfs_block_short_extent *rv = NULL;
+
+       spin_lock_bh(&marks->im_lock);
+       if (!list_empty(&marks->im_extents)) {
+               rv = list_entry((&marks->im_extents)->next,
+                               struct pnfs_block_short_extent, bse_node);
+               list_del_init(&rv->bse_node);
+       }
+       spin_unlock_bh(&marks->im_lock);
+
+       return rv;
+}
+
+void bl_free_short_extents(struct pnfs_inval_markings *marks, int num_to_free)
+{
+       struct pnfs_block_short_extent *se = NULL, *tmp;
+
+       if (num_to_free <= 0)
+               return;
+
+       spin_lock(&marks->im_lock);
+       list_for_each_entry_safe(se, tmp, &marks->im_extents, bse_node) {
+               list_del(&se->bse_node);
+               kfree(se);
+               if (--num_to_free == 0)
+                       break;
+       }
+       spin_unlock(&marks->im_lock);
+
+       BUG_ON(num_to_free > 0);
+}
index 07df5f1d85e5188b16d51f13049dd925870b5238..c89d3b9e483c463cb1b9232e4b97520a7b7e1eaf 100644 (file)
@@ -162,7 +162,7 @@ struct cb_layoutrecallargs {
        };
 };
 
-extern unsigned nfs4_callback_layoutrecall(
+extern __be32 nfs4_callback_layoutrecall(
        struct cb_layoutrecallargs *args,
        void *dummy, struct cb_process_state *cps);
 
index 726e59a9e50f6ad20471895793efdb171aed7dd7..d50b2742f23baeb20d54c44d6919ed126faf74c8 100644 (file)
@@ -305,6 +305,10 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
        n = ntohl(*p++);
        if (n <= 0)
                goto out;
+       if (n > ULONG_MAX / sizeof(*args->devs)) {
+               status = htonl(NFS4ERR_BADXDR);
+               goto out;
+       }
 
        args->devs = kmalloc(n * sizeof(*args->devs), GFP_KERNEL);
        if (!args->devs) {
index ed388aae96893628dfcecb25743acac320b8a1b4..8ae91908f5aa6fa38c128348beb272ddb6226a3b 100644 (file)
@@ -382,7 +382,7 @@ decode_ds_addr(struct xdr_stream *streamp, gfp_t gfp_flags)
 {
        struct nfs4_pnfs_ds_addr *da = NULL;
        char *buf, *portstr;
-       u32 port;
+       __be16 port;
        int nlen, rlen;
        int tmp[2];
        __be32 *p;
index 75366dc89686d88655c6569f4840a1651ca98690..f0c849c98fe4bfb49208ed6a34f0714257431e75 100644 (file)
@@ -3587,7 +3587,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                res.acl_flags |= NFS4_ACL_LEN_REQUEST;
        resp_buf = page_address(pages[0]);
 
-       dprintk("%s  buf %p buflen %ld npages %d args.acl_len %ld\n",
+       dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
                __func__, buf, buflen, npages, args.acl_len);
        ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
                             &msg, &args.seq_args, &res.seq_res, 0);
index 1b1094c35e4fd979f6b49d35b9f6c725ee0eac9b..cb4428ab81ed5627bf2ea7ed3dc2c4ea414bfce9 100644 (file)
@@ -72,7 +72,7 @@ typedef enum fe_caps {
 
 struct dvb_frontend_info {
        char       name[128];
-       fe_type_t  type;
+       fe_type_t  type;                        /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
        __u32      frequency_min;
        __u32      frequency_max;
        __u32      frequency_stepsize;
@@ -181,6 +181,7 @@ typedef enum fe_transmit_mode {
        TRANSMISSION_MODE_32K,
 } fe_transmit_mode_t;
 
+#if defined(__DVB_CORE__) || !defined (__KERNEL__)
 typedef enum fe_bandwidth {
        BANDWIDTH_8_MHZ,
        BANDWIDTH_7_MHZ,
@@ -190,7 +191,7 @@ typedef enum fe_bandwidth {
        BANDWIDTH_10_MHZ,
        BANDWIDTH_1_712_MHZ,
 } fe_bandwidth_t;
-
+#endif
 
 typedef enum fe_guard_interval {
        GUARD_INTERVAL_1_32,
@@ -213,6 +214,7 @@ typedef enum fe_hierarchy {
 } fe_hierarchy_t;
 
 
+#if defined(__DVB_CORE__) || !defined (__KERNEL__)
 struct dvb_qpsk_parameters {
        __u32           symbol_rate;  /* symbol rate in Symbols per second */
        fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
@@ -251,11 +253,11 @@ struct dvb_frontend_parameters {
        } u;
 };
 
-
 struct dvb_frontend_event {
        fe_status_t status;
        struct dvb_frontend_parameters parameters;
 };
+#endif
 
 /* S2API Commands */
 #define DTV_UNDEFINED          0
@@ -316,7 +318,9 @@ struct dvb_frontend_event {
 
 #define DTV_DVBT2_PLP_ID       43
 
-#define DTV_MAX_COMMAND                                DTV_DVBT2_PLP_ID
+#define DTV_ENUM_DELSYS                44
+
+#define DTV_MAX_COMMAND                                DTV_ENUM_DELSYS
 
 typedef enum fe_pilot {
        PILOT_ON,
@@ -333,7 +337,7 @@ typedef enum fe_rolloff {
 
 typedef enum fe_delivery_system {
        SYS_UNDEFINED,
-       SYS_DVBC_ANNEX_AC,
+       SYS_DVBC_ANNEX_A,
        SYS_DVBC_ANNEX_B,
        SYS_DVBT,
        SYS_DSS,
@@ -350,8 +354,13 @@ typedef enum fe_delivery_system {
        SYS_DAB,
        SYS_DVBT2,
        SYS_TURBO,
+       SYS_DVBC_ANNEX_C,
 } fe_delivery_system_t;
 
+
+#define SYS_DVBC_ANNEX_AC      SYS_DVBC_ANNEX_A
+
+
 struct dtv_cmds_h {
        char    *name;          /* A display name for debugging purposes */
 
index 66594b1d5d7b01a766c359ce96d3e6dbc290c984..0559e2bd38f96e54df84936a78bac5cc7fba5365 100644 (file)
@@ -24,6 +24,6 @@
 #define _DVBVERSION_H_
 
 #define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 4
+#define DVB_API_VERSION_MINOR 5
 
 #endif /*_DVBVERSION_H_*/
index ecdaeb98b293727274b6511ee7ef523c00324564..5cf685086dd3f6d728b6a0374f096a080b1bfc1d 100644 (file)
@@ -312,7 +312,6 @@ struct tty_driver {
         */
        struct tty_struct **ttys;
        struct ktermios **termios;
-       struct ktermios **termios_locked;
        void *driver_state;
 
        /*
index d2f74f8e3fe3db414e76ce72a7a2aa6a7a05a10f..5e11f8a1f8674aa0465a310f862c7c3df9cc7cf0 100644 (file)
@@ -403,6 +403,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
 #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
 #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */
 #define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
 #define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
 #define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
@@ -744,6 +745,48 @@ struct v4l2_crop {
        struct v4l2_rect        c;
 };
 
+/* Hints for adjustments of selection rectangle */
+#define V4L2_SEL_FLAG_GE       0x00000001
+#define V4L2_SEL_FLAG_LE       0x00000002
+
+/* Selection targets */
+
+/* current cropping area */
+#define V4L2_SEL_TGT_CROP_ACTIVE       0
+/* default cropping area */
+#define V4L2_SEL_TGT_CROP_DEFAULT      1
+/* cropping bounds */
+#define V4L2_SEL_TGT_CROP_BOUNDS       2
+/* current composing area */
+#define V4L2_SEL_TGT_COMPOSE_ACTIVE    256
+/* default composing area */
+#define V4L2_SEL_TGT_COMPOSE_DEFAULT   257
+/* composing bounds */
+#define V4L2_SEL_TGT_COMPOSE_BOUNDS    258
+/* current composing area plus all padding pixels */
+#define V4L2_SEL_TGT_COMPOSE_PADDED    259
+
+/**
+ * struct v4l2_selection - selection info
+ * @type:      buffer type (do not use *_MPLANE types)
+ * @target:    selection target, used to choose one of possible rectangles
+ * @flags:     constraints flags
+ * @r:         coordinates of selection window
+ * @reserved:  for future use, rounds structure size to 64 bytes, set to zero
+ *
+ * Hardware may use multiple helper window to process a video stream.
+ * The structure is used to exchange this selection areas between
+ * an application and a driver.
+ */
+struct v4l2_selection {
+       __u32                   type;
+       __u32                   target;
+       __u32                   flags;
+       struct v4l2_rect        r;
+       __u32                   reserved[9];
+};
+
+
 /*
  *      A N A L O G   V I D E O   S T A N D A R D
  */
@@ -1133,6 +1176,7 @@ struct v4l2_querymenu {
 #define V4L2_CTRL_FLAG_NEXT_CTRL       0x80000000
 
 /*  User-class control IDs defined by V4L2 */
+#define V4L2_CID_MAX_CTRLS             1024
 #define V4L2_CID_BASE                  (V4L2_CTRL_CLASS_USER | 0x900)
 #define V4L2_CID_USER_BASE             V4L2_CID_BASE
 /*  IDs reserved for driver specific controls */
@@ -1206,10 +1250,10 @@ enum v4l2_colorfx {
 #define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE       (V4L2_CID_BASE+39)
 #define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT                (V4L2_CID_BASE+40)
 
-/* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+41)
+#define V4L2_CID_ALPHA_COMPONENT               (V4L2_CID_BASE+41)
 
-/* Minimum number of buffer neede by the device */
+/* last CID + 1 */
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+42)
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1684,6 +1728,8 @@ enum v4l2_flash_strobe_source {
 #define V4L2_FLASH_FAULT_TIMEOUT               (1 << 1)
 #define V4L2_FLASH_FAULT_OVER_TEMPERATURE      (1 << 2)
 #define V4L2_FLASH_FAULT_SHORT_CIRCUIT         (1 << 3)
+#define V4L2_FLASH_FAULT_OVER_CURRENT          (1 << 4)
+#define V4L2_FLASH_FAULT_INDICATOR             (1 << 5)
 
 #define V4L2_CID_FLASH_CHARGE                  (V4L2_CID_FLASH_CLASS_BASE + 11)
 #define V4L2_CID_FLASH_READY                   (V4L2_CID_FLASH_CLASS_BASE + 12)
@@ -2257,6 +2303,10 @@ struct v4l2_create_buffers {
 #define VIDIOC_CREATE_BUFS     _IOWR('V', 92, struct v4l2_create_buffers)
 #define VIDIOC_PREPARE_BUF     _IOWR('V', 93, struct v4l2_buffer)
 
+/* Experimental selection API */
+#define VIDIOC_G_SELECTION     _IOWR('V', 94, struct v4l2_selection)
+#define VIDIOC_S_SELECTION     _IOWR('V', 95, struct v4l2_selection)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
diff --git a/include/media/as3645a.h b/include/media/as3645a.h
new file mode 100644 (file)
index 0000000..5075496
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * include/media/as3645a.h
+ *
+ * Copyright (C) 2008-2011 Nokia Corporation
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __AS3645A_H__
+#define __AS3645A_H__
+
+#include <media/v4l2-subdev.h>
+
+#define AS3645A_NAME                           "as3645a"
+#define AS3645A_I2C_ADDR                       (0x60 >> 1) /* W:0x60, R:0x61 */
+
+#define AS3645A_FLASH_TIMEOUT_MIN              100000  /* us */
+#define AS3645A_FLASH_TIMEOUT_MAX              850000
+#define AS3645A_FLASH_TIMEOUT_STEP             50000
+
+#define AS3645A_FLASH_INTENSITY_MIN            200     /* mA */
+#define AS3645A_FLASH_INTENSITY_MAX_1LED       500
+#define AS3645A_FLASH_INTENSITY_MAX_2LEDS      400
+#define AS3645A_FLASH_INTENSITY_STEP           20
+
+#define AS3645A_TORCH_INTENSITY_MIN            20      /* mA */
+#define AS3645A_TORCH_INTENSITY_MAX            160
+#define AS3645A_TORCH_INTENSITY_STEP           20
+
+#define AS3645A_INDICATOR_INTENSITY_MIN                0       /* uA */
+#define AS3645A_INDICATOR_INTENSITY_MAX                10000
+#define AS3645A_INDICATOR_INTENSITY_STEP       2500
+
+/*
+ * as3645a_platform_data - Flash controller platform data
+ * @set_power: Set power callback
+ * @vref:      VREF offset (0=0V, 1=+0.3V, 2=-0.3V, 3=+0.6V)
+ * @peak:      Inductor peak current limit (0=1.25A, 1=1.5A, 2=1.75A, 3=2.0A)
+ * @ext_strobe:        True if external flash strobe can be used
+ * @flash_max_current: Max flash current (mA, <= AS3645A_FLASH_INTENSITY_MAX)
+ * @torch_max_current: Max torch current (mA, >= AS3645A_TORCH_INTENSITY_MAX)
+ * @timeout_max:       Max flash timeout (us, <= AS3645A_FLASH_TIMEOUT_MAX)
+ */
+struct as3645a_platform_data {
+       int (*set_power)(struct v4l2_subdev *subdev, int on);
+       unsigned int vref;
+       unsigned int peak;
+       bool ext_strobe;
+
+       /* Flash and torch currents and timeout limits */
+       unsigned int flash_max_current;
+       unsigned int torch_max_current;
+       unsigned int timeout_max;
+};
+
+#endif /* __AS3645A_H__ */
index 26cece5951218072e249327561ba5289c60575d7..656823075709d6728cc2b2ec182e4827d5b319f1 100644 (file)
@@ -110,10 +110,12 @@ struct isi_platform_data {
        u8 hsync_act_low;
        u8 vsync_act_low;
        u8 pclk_act_falling;
-       u8 isi_full_mode;
+       u8 full_mode;
        u32 data_width_flags;
        /* Using for ISI_CFG1 */
        u32 frate;
+       /* Using for ISI_MCK */
+       u32 mck_hz;
 };
 
 #endif /* __ATMEL_ISI_H__ */
index 46d1a141208ef5fc9e768615ce21ba5a05c1d510..783c5bdd63eb8132acc98cb4115986004ffce29a 100644 (file)
@@ -85,6 +85,7 @@ enum cx25840_video_input {
        CX25840_NONE1_CH3 = 0x800000c0,
        CX25840_SVIDEO_ON = 0x80000100,
        CX25840_COMPONENT_ON = 0x80000200,
+       CX25840_DIF_ON = 0x80000400,
 };
 
 enum cx25840_audio_input {
index 8b11fb0379801737b510f063a9a8c341caeeb991..8bc1b3c0e6790501d1853e59841867f5709afed4 100644 (file)
@@ -63,6 +63,7 @@ struct vpbe_output {
         * output basis. If per mode is needed, we may have to move this to
         * mode_info structure
         */
+       enum v4l2_mbus_pixelcode if_params;
 };
 
 /* encoder configuration info */
@@ -74,6 +75,15 @@ struct encoder_config_info {
        struct i2c_board_info board_info;
 };
 
+/*amplifier configuration info */
+struct amp_config_info {
+       char module_name[32];
+       /* Is this an i2c device ? */
+       unsigned int is_i2c:1;
+       /* i2c subdevice board info */
+       struct i2c_board_info board_info;
+};
+
 /* structure for defining vpbe display subsystem components */
 struct vpbe_config {
        char module_name[32];
@@ -84,6 +94,8 @@ struct vpbe_config {
        /* external encoder information goes here */
        int num_ext_encoders;
        struct encoder_config_info *ext_encoders;
+       /* amplifier information goes here */
+       struct amp_config_info *amp;
        int num_outputs;
        /* Order is venc outputs followed by LCD and then external encoders */
        struct vpbe_output *outputs;
@@ -158,6 +170,8 @@ struct vpbe_device {
        struct v4l2_subdev **encoders;
        /* current encoder index */
        int current_sd_index;
+       /* external amplifier v4l2 subdevice */
+       struct v4l2_subdev *amp;
        struct mutex lock;
        /* device initialized */
        int initialized;
@@ -165,6 +179,8 @@ struct vpbe_device {
        struct clk *dac_clk;
        /* osd_device pointer */
        struct osd_state *osd_device;
+       /* venc device pointer */
+       struct venc_platform_data *venc_device;
        /*
         * fields below are accessed by users of vpbe_device. Not the
         * ones above
index 426c205831a2f73681366f0293c3fdc27809b140..6b57334f402996341e584fcc0177054140663ba5 100644 (file)
 
 struct venc_platform_data {
        enum vpbe_version venc_type;
+       int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
+                           int field);
        int (*setup_clock)(enum vpbe_enc_timings_type type,
                           unsigned int mode);
+       int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
        /* Number of LCD outputs supported */
        int num_lcd_outputs;
+       struct vpbe_if_params *lcd_if_params;
 };
 
 enum venc_ioctls {
index cd8bca63a502975340839b9c54174bc44ba17f97..29e7bba78ffeb540f597e25ac3b221ed88001267 100644 (file)
@@ -98,7 +98,7 @@ struct media_entity {
 
                /* Sub-device specifications */
                /* Nothing needed yet */
-       };
+       } info;
 };
 
 static inline u32 media_entity_type(struct media_entity *entity)
index e917b1da65778088b3e2b00239587e589138be48..042849a34640994e34d49a6815702e1db102b029 100644 (file)
@@ -58,7 +58,7 @@ enum {
  *             ISP_LANE_SHIFT_4 - CAMEXT[13:4] -> CAM[9:0]
  *             ISP_LANE_SHIFT_6 - CAMEXT[13:6] -> CAM[7:0]
  * @clk_pol: Pixel clock polarity
- *             0 - Non Inverted, 1 - Inverted
+ *             0 - Sample on rising edge, 1 - Sample on falling edge
  * @hs_pol: Horizontal synchronization polarity
  *             0 - Active high, 1 - Active low
  * @vs_pol: Vertical synchronization polarity
diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h
deleted file mode 100644 (file)
index 1ed1e61..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-#ifndef PWC_IOCTL_H
-#define PWC_IOCTL_H
-
-/* (C) 2001-2004 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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
-*/
-
-/* This is pwc-ioctl.h belonging to PWC 10.0.10
-   It contains structures and defines to communicate from user space
-   directly to the driver.
- */
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added ioctl constants to access methods for
-                         changing white balance and red/blue gains
-   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
-   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
-              PWCX easier
-   2006/01/01  Luc Saillard Add raw format definition
- */
-
-/* These are private ioctl() commands, specific for the Philips webcams.
-   They contain functions not found in other webcams, and settings not
-   specified in the Video4Linux API.
-
-   The #define names are built up like follows:
-   VIDIOC              VIDeo IOCtl prefix
-        PWC            Philps WebCam
-           G           optional: Get
-           S           optional: Set
-            ...        the function
- */
-
-#include <linux/types.h>
-
-/* Enumeration of image sizes */
-#define PSZ_SQCIF      0x00
-#define PSZ_QSIF       0x01
-#define PSZ_QCIF       0x02
-#define PSZ_SIF                0x03
-#define PSZ_CIF                0x04
-#define PSZ_VGA                0x05
-#define PSZ_MAX                6
-
-
-/* The frame rate is encoded in the video_window.flags parameter using
-   the upper 16 bits, since some flags are defined nowadays. The following
-   defines provide a mask and shift to filter out this value.
-   This value can also be passing using the private flag when using v4l2 and
-   VIDIOC_S_FMT ioctl.
-
-   In 'Snapshot' mode the camera freezes its automatic exposure and colour
-   balance controls.
- */
-#define PWC_FPS_SHIFT          16
-#define PWC_FPS_MASK           0x00FF0000
-#define PWC_FPS_FRMASK         0x003F0000
-#define PWC_FPS_SNAPSHOT       0x00400000
-#define PWC_QLT_MASK           0x03000000
-#define PWC_QLT_SHIFT          24
-
-
-/* structure for transferring x & y coordinates */
-struct pwc_coord
-{
-       int x, y;               /* guess what */
-       int size;               /* size, or offset */
-};
-
-
-/* Used with VIDIOCPWCPROBE */
-struct pwc_probe
-{
-       char name[32];
-       int type;
-};
-
-struct pwc_serial
-{
-       char serial[30];        /* String with serial number. Contains terminating 0 */
-};
-
-/* pwc_whitebalance.mode values */
-#define PWC_WB_INDOOR          0
-#define PWC_WB_OUTDOOR         1
-#define PWC_WB_FL              2
-#define PWC_WB_MANUAL          3
-#define PWC_WB_AUTO            4
-
-/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
-   Set mode to one of the PWC_WB_* values above.
-   *red and *blue are the respective gains of these colour components inside
-   the camera; range 0..65535
-   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
-   otherwise undefined.
-   'read_red' and 'read_blue' are read-only.
-*/
-struct pwc_whitebalance
-{
-       int mode;
-       int manual_red, manual_blue;    /* R/W */
-       int read_red, read_blue;        /* R/O */
-};
-
-/*
-   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
-   and tell the camera how fast it should react to changes in lighting, and
-   with how much delay. Valid values are 0..65535.
-*/
-struct pwc_wb_speed
-{
-       int control_speed;
-       int control_delay;
-
-};
-
-/* Used with VIDIOCPWC[SG]LED */
-struct pwc_leds
-{
-       int led_on;                     /* Led on-time; range = 0..25000 */
-       int led_off;                    /* Led off-time; range = 0..25000  */
-};
-
-/* Image size (used with GREALSIZE) */
-struct pwc_imagesize
-{
-       int width;
-       int height;
-};
-
-/* Defines and structures for Motorized Pan & Tilt */
-#define PWC_MPT_PAN            0x01
-#define PWC_MPT_TILT           0x02
-#define PWC_MPT_TIMEOUT                0x04 /* for status */
-
-/* Set angles; when absolute != 0, the angle is absolute and the
-   driver calculates the relative offset for you. This can only
-   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
-   absolute angles.
- */
-struct pwc_mpt_angles
-{
-       int absolute;           /* write-only */
-       int pan;                /* degrees * 100 */
-       int tilt;               /* degress * 100 */
-};
-
-/* Range of angles of the camera, both horizontally and vertically.
- */
-struct pwc_mpt_range
-{
-       int pan_min, pan_max;           /* degrees * 100 */
-       int tilt_min, tilt_max;
-};
-
-struct pwc_mpt_status
-{
-       int status;
-       int time_pan;
-       int time_tilt;
-};
-
-
-/* This is used for out-of-kernel decompression. With it, you can get
-   all the necessary information to initialize and use the decompressor
-   routines in standalone applications.
- */
-struct pwc_video_command
-{
-       int type;               /* camera type (645, 675, 730, etc.) */
-       int release;            /* release number */
-
-       int size;               /* one of PSZ_* */
-       int alternate;
-       int command_len;        /* length of USB video command */
-       unsigned char command_buf[13];  /* Actual USB video command */
-       int bandlength;         /* >0 = compressed */
-       int frame_size;         /* Size of one (un)compressed frame */
-};
-
-/* Flags for PWCX subroutines. Not all modules honour all flags. */
-#define PWCX_FLAG_PLANAR       0x0001
-#define PWCX_FLAG_BAYER                0x0008
-
-
-/* IOCTL definitions */
-
- /* Restore user settings */
-#define VIDIOCPWCRUSER         _IO('v', 192)
- /* Save user settings */
-#define VIDIOCPWCSUSER         _IO('v', 193)
- /* Restore factory settings */
-#define VIDIOCPWCFACTORY       _IO('v', 194)
-
- /* You can manipulate the compression factor. A compression preference of 0
-    means use uncompressed modes when available; 1 is low compression, 2 is
-    medium and 3 is high compression preferred. Of course, the higher the
-    compression, the lower the bandwidth used but more chance of artefacts
-    in the image. The driver automatically chooses a higher compression when
-    the preferred mode is not available.
-  */
- /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
-#define VIDIOCPWCSCQUAL                _IOW('v', 195, int)
- /* Get preferred compression quality */
-#define VIDIOCPWCGCQUAL                _IOR('v', 195, int)
-
-
-/* Retrieve serial number of camera */
-#define VIDIOCPWCGSERIAL       _IOR('v', 198, struct pwc_serial)
-
- /* This is a probe function; since so many devices are supported, it
-    becomes difficult to include all the names in programs that want to
-    check for the enhanced Philips stuff. So in stead, try this PROBE;
-    it returns a structure with the original name, and the corresponding
-    Philips type.
-    To use, fill the structure with zeroes, call PROBE and if that succeeds,
-    compare the name with that returned from VIDIOCGCAP; they should be the
-    same. If so, you can be assured it is a Philips (OEM) cam and the type
-    is valid.
- */
-#define VIDIOCPWCPROBE         _IOR('v', 199, struct pwc_probe)
-
- /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
-#define VIDIOCPWCSAGC          _IOW('v', 200, int)
- /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCGAGC          _IOR('v', 200, int)
- /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCSSHUTTER      _IOW('v', 201, int)
-
- /* Color compensation (Auto White Balance) */
-#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
-#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
-
- /* Auto WB speed */
-#define VIDIOCPWCSAWBSPEED     _IOW('v', 203, struct pwc_wb_speed)
-#define VIDIOCPWCGAWBSPEED     _IOR('v', 203, struct pwc_wb_speed)
-
- /* LEDs on/off/blink; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
-#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
-
-  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
-#define VIDIOCPWCSCONTOUR      _IOW('v', 206, int)
-#define VIDIOCPWCGCONTOUR      _IOR('v', 206, int)
-
-  /* Backlight compensation; 0 = off, otherwise on */
-#define VIDIOCPWCSBACKLIGHT    _IOW('v', 207, int)
-#define VIDIOCPWCGBACKLIGHT    _IOR('v', 207, int)
-
-  /* Flickerless mode; = 0 off, otherwise on */
-#define VIDIOCPWCSFLICKER      _IOW('v', 208, int)
-#define VIDIOCPWCGFLICKER      _IOR('v', 208, int)
-
-  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
-#define VIDIOCPWCSDYNNOISE     _IOW('v', 209, int)
-#define VIDIOCPWCGDYNNOISE     _IOR('v', 209, int)
-
- /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
-#define VIDIOCPWCGREALSIZE     _IOR('v', 210, struct pwc_imagesize)
-
- /* Motorized pan & tilt functions */
-#define VIDIOCPWCMPTRESET      _IOW('v', 211, int)
-#define VIDIOCPWCMPTGRANGE     _IOR('v', 211, struct pwc_mpt_range)
-#define VIDIOCPWCMPTSANGLE     _IOW('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTGANGLE     _IOR('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTSTATUS     _IOR('v', 213, struct pwc_mpt_status)
-
- /* Get the USB set-video command; needed for initializing libpwcx */
-#define VIDIOCPWCGVIDCMD       _IOR('v', 215, struct pwc_video_command)
-struct pwc_table_init_buffer {
-   int len;
-   char *buffer;
-
-};
-#define VIDIOCPWCGVIDTABLE     _IOR('v', 216, struct pwc_table_init_buffer)
-
-/*
- * This is private command used when communicating with v4l2.
- * In the future all private ioctl will be remove/replace to
- * use interface offer by v4l2.
- */
-
-#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
-
-struct pwc_raw_frame {
-   __le16 type;                /* type of the webcam */
-   __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
-   __u8   cmd[4];      /* the four byte of the command (in case of nala,
-                          only the first 3 bytes is filled) */
-   __u8   rawframe[0]; /* frame_size = H/4*vbandlength */
-} __attribute__ ((packed));
-
-
-#endif
index 26a3bd0fe57ca7a393afe27c1004970f5354a701..f688bde61228ce8ec4d6f2753c2408a972dedb99 100644 (file)
 #define RC_TYPE_JVC    (1  << 3)       /* JVC protocol */
 #define RC_TYPE_SONY   (1  << 4)       /* Sony12/15/20 protocol */
 #define RC_TYPE_RC5_SZ (1  << 5)       /* RC5 variant used by Streamzap */
+#define RC_TYPE_SANYO   (1  << 6)      /* Sanyo protocol */
 #define RC_TYPE_MCE_KBD        (1  << 29)      /* RC6-ish MCE keyboard/mouse */
 #define RC_TYPE_LIRC   (1  << 30)      /* Pass raw IR to lirc userspace */
 #define RC_TYPE_OTHER  (1u << 31)
 
-#define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC  | RC_TYPE_RC6  | \
-                    RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \
-                    RC_TYPE_RC5_SZ | RC_TYPE_MCE_KBD | RC_TYPE_OTHER)
+#define RC_TYPE_ALL (RC_TYPE_RC5    | RC_TYPE_NEC   | RC_TYPE_RC6     | \
+                    RC_TYPE_JVC    | RC_TYPE_SONY  | RC_TYPE_LIRC    | \
+                    RC_TYPE_RC5_SZ | RC_TYPE_SANYO | RC_TYPE_MCE_KBD | \
+                    RC_TYPE_OTHER)
 
 struct rc_map_table {
        u32     scancode;
@@ -145,7 +147,7 @@ void rc_map_init(void);
 #define RC_MAP_TREKSTOR                  "rc-trekstor"
 #define RC_MAP_TT_1500                   "rc-tt-1500"
 #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
-#define RC_MAP_VIDEOMATE_M1F             "rc-videomate-m1f"
+#define RC_MAP_VIDEOMATE_K100            "rc-videomate-k100"
 #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
 #define RC_MAP_VIDEOMATE_TV_PVR          "rc-videomate-tv-pvr"
 #define RC_MAP_WINFAST                   "rc-winfast"
index 5fb2c3d10c05047a4c50fb2e4440e7862a6a9908..b5c2b6cb0d81078f23fb3a6c1c779e90e31b88ce 100644 (file)
@@ -94,7 +94,7 @@ struct soc_camera_host_ops {
                              struct soc_camera_device *);
        int (*reqbufs)(struct soc_camera_device *, struct v4l2_requestbuffers *);
        int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
-       int (*set_bus_param)(struct soc_camera_device *, __u32);
+       int (*set_bus_param)(struct soc_camera_device *);
        int (*get_parm)(struct soc_camera_device *, struct v4l2_streamparm *);
        int (*set_parm)(struct soc_camera_device *, struct v4l2_streamparm *);
        int (*enum_fsizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *);
index 4d1c74ad4c84626b8fb6e96a9249dbb2b1c2cb33..3f5d60fc5df689845cfb731d61bee2b3f0e48673 100644 (file)
@@ -196,6 +196,10 @@ struct v4l2_ioctl_ops {
                                        struct v4l2_crop *a);
        int (*vidioc_s_crop)           (struct file *file, void *fh,
                                        struct v4l2_crop *a);
+       int (*vidioc_g_selection)      (struct file *file, void *fh,
+                                       struct v4l2_selection *s);
+       int (*vidioc_s_selection)      (struct file *file, void *fh,
+                                       struct v4l2_selection *s);
        /* Compression ioctls */
        int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
                                        struct v4l2_jpegcompression *a);
index 9324488f23f0b2eaab58e50f7cdda0b6d4b152ef..ee338bfde18b25d45bb0252ff41ea4160095d6e7 100644 (file)
@@ -84,6 +84,21 @@ typedef uint64_t blkif_sector_t;
  *     e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
  * http://www.seagate.com/staticfiles/support/disc/manuals/
  *     Interface%20manuals/100293068c.pdf
+ * The backend can optionally provide three extra XenBus attributes to
+ * further optimize the discard functionality:
+ * 'discard-aligment' - Devices that support discard functionality may
+ * internally allocate space in units that are bigger than the exported
+ * logical block size. The discard-alignment parameter indicates how many bytes
+ * the beginning of the partition is offset from the internal allocation unit's
+ * natural alignment.
+ * 'discard-granularity'  - Devices that support discard functionality may
+ * internally allocate space using units that are bigger than the logical block
+ * size. The discard-granularity parameter indicates the size of the internal
+ * allocation unit in bytes if reported by the device. Otherwise the
+ * discard-granularity will be set to match the device's physical block size.
+ * 'discard-secure' - All copies of the discarded sectors (potentially created
+ * by garbage collection) must also be erased.  To use this feature, the flag
+ * BLKIF_DISCARD_SECURE must be set in the blkif_request_trim.
  */
 #define BLKIF_OP_DISCARD           5
 
@@ -95,6 +110,12 @@ typedef uint64_t blkif_sector_t;
 #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
 
 struct blkif_request_rw {
+       uint8_t        nr_segments;  /* number of segments                   */
+       blkif_vdev_t   handle;       /* only for read/write requests         */
+#ifdef CONFIG_X86_64
+       uint32_t       _pad1;        /* offsetof(blkif_request,u.rw.id) == 8 */
+#endif
+       uint64_t       id;           /* private guest value, echoed in resp  */
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
        struct blkif_request_segment {
                grant_ref_t gref;        /* reference to I/O buffer frame        */
@@ -102,23 +123,28 @@ struct blkif_request_rw {
                /* @last_sect: last sector in frame to transfer (inclusive).     */
                uint8_t     first_sect, last_sect;
        } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
 
 struct blkif_request_discard {
+       uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero.        */
+#define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0          */
+       blkif_vdev_t   _pad1;        /* only for read/write requests         */
+#ifdef CONFIG_X86_64
+       uint32_t       _pad2;        /* offsetof(blkif_req..,u.discard.id)==8*/
+#endif
+       uint64_t       id;           /* private guest value, echoed in resp  */
        blkif_sector_t sector_number;
-       uint64_t nr_sectors;
-};
+       uint64_t       nr_sectors;
+       uint8_t        _pad3;
+} __attribute__((__packed__));
 
 struct blkif_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
-       uint8_t        nr_segments;  /* number of segments                   */
-       blkif_vdev_t   handle;       /* only for read/write requests         */
-       uint64_t       id;           /* private guest value, echoed in resp  */
        union {
                struct blkif_request_rw rw;
                struct blkif_request_discard discard;
        } u;
-};
+} __attribute__((__packed__));
 
 struct blkif_response {
        uint64_t        id;              /* copied from request */
index f70396e5a24b8cef95d994ed612aca85beaaac92..2d9de86b7e767f518e59183a98bf4c04e0038813 100644 (file)
@@ -23,6 +23,7 @@ CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
 obj-y += sched/
+obj-y += power/
 
 obj-$(CONFIG_FREEZER) += freezer.o
 obj-$(CONFIG_PROFILING) += profile.o
@@ -52,8 +53,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
-obj-$(CONFIG_PM) += power/
-obj-$(CONFIG_FREEZER) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
index 0fcf1c14a297c57d7cda541b71438441dd1adbde..3f1adb6c647015d80aa6b5b138f118fde7484d11 100644 (file)
@@ -384,7 +384,7 @@ bool ns_capable(struct user_namespace *ns, int cap)
                BUG();
        }
 
-       if (has_ns_capability(current, ns, cap)) {
+       if (security_capable(current_cred(), ns, cap) == 0) {
                current->flags |= PF_SUPERPRIV;
                return true;
        }
index acf6ed3ebe81f98605f004a0feb40f70bd089a4a..2c932760fd33d152016e62431cba5c986f65957f 100644 (file)
@@ -842,26 +842,6 @@ out:
        return ret;
 }
 
-static size_t module_flags_taint(struct module *mod, char *buf)
-{
-       size_t l = 0;
-
-       if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
-               buf[l++] = 'P';
-       if (mod->taints & (1 << TAINT_OOT_MODULE))
-               buf[l++] = 'O';
-       if (mod->taints & (1 << TAINT_FORCED_MODULE))
-               buf[l++] = 'F';
-       if (mod->taints & (1 << TAINT_CRAP))
-               buf[l++] = 'C';
-       /*
-        * TAINT_FORCED_RMMOD: could be added.
-        * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
-        * apply to modules.
-        */
-       return l;
-}
-
 static inline void print_unload_info(struct seq_file *m, struct module *mod)
 {
        struct module_use *use;
@@ -962,6 +942,26 @@ static inline int module_unload_init(struct module *mod)
 }
 #endif /* CONFIG_MODULE_UNLOAD */
 
+static size_t module_flags_taint(struct module *mod, char *buf)
+{
+       size_t l = 0;
+
+       if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
+               buf[l++] = 'P';
+       if (mod->taints & (1 << TAINT_OOT_MODULE))
+               buf[l++] = 'O';
+       if (mod->taints & (1 << TAINT_FORCED_MODULE))
+               buf[l++] = 'F';
+       if (mod->taints & (1 << TAINT_CRAP))
+               buf[l++] = 'C';
+       /*
+        * TAINT_FORCED_RMMOD: could be added.
+        * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
+        * apply to modules.
+        */
+       return l;
+}
+
 static ssize_t show_initstate(struct module_attribute *mattr,
                              struct module_kobject *mk, char *buffer)
 {
index 3739ecced085db0141557feec608bb3eccbb0c07..8742fd013a94e3b56efdbf91cf27c709679615e4 100644 (file)
@@ -773,8 +773,7 @@ static int enough_swap(unsigned int nr_pages, unsigned int flags)
 
        pr_debug("PM: Free swap pages: %u\n", free_swap);
 
-       required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ?
-               nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
+       required = PAGES_FOR_IO + nr_pages;
        return free_swap > required;
 }
 
@@ -802,10 +801,12 @@ int swsusp_write(unsigned int flags)
                printk(KERN_ERR "PM: Cannot get swap writer\n");
                return error;
        }
-       if (!enough_swap(pages, flags)) {
-               printk(KERN_ERR "PM: Not enough free swap\n");
-               error = -ENOSPC;
-               goto out_finish;
+       if (flags & SF_NOCOMPRESS_MODE) {
+               if (!enough_swap(pages, flags)) {
+                       printk(KERN_ERR "PM: Not enough free swap\n");
+                       error = -ENOSPC;
+                       goto out_finish;
+               }
        }
        memset(&snapshot, 0, sizeof(struct snapshot_handle));
        error = snapshot_read_next(&snapshot);
index a57f5bd5a13d5b8f14a90b03bf23115e925b4a0a..d3bae5e7b6018d7429c518681a706179e00c6d81 100644 (file)
@@ -4,12 +4,16 @@
 # header-y  - list files to be installed. They are preprocessed
 #             to remove __KERNEL__ section of the file
 # objhdr-y  - Same as header-y but for generated files
+# genhdr-y  - Same as objhdr-y but in a generated/ directory
 #
 # ==========================================================================
 
 # called may set destination dir (when installing to asm/)
 _dst := $(if $(dst),$(dst),$(obj))
 
+# generated header directory
+gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
+
 kbuild-file := $(srctree)/$(obj)/Kbuild
 include $(kbuild-file)
 
@@ -33,9 +37,10 @@ wrapper-files := $(filter $(header-y), $(generic-y))
 
 # all headers files for this dir
 header-y      := $(filter-out $(generic-y), $(header-y))
-all-files     := $(header-y) $(objhdr-y) $(wrapper-files)
+all-files     := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files)
 input-files   := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
-                 $(addprefix $(objtree)/$(obj)/,$(objhdr-y))
+                 $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \
+                 $(addprefix $(objtree)/$(gen)/,$(genhdr-y))
 output-files  := $(addprefix $(install)/, $(all-files))
 
 # Work out what needs to be removed
@@ -52,6 +57,7 @@ quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
       cmd_install = \
         $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \
         $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \
+        $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \
         for F in $(wrapper-files); do                                   \
                 echo "\#include <asm-generic/$$F>" > $(install)/$$F;    \
         done;                                                           \
index 5d986d9adf1b7977684a1fa1825f5ff25c2816bc..00c368c6e996fb0555f8161b6d3147c554d037e5 100644 (file)
@@ -93,9 +93,9 @@ obj-dirs      := $(addprefix $(obj)/,$(obj-dirs))
 # already
 # $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will 
 # end up in (or would, if it gets compiled in)
-# Note: It's possible that one object gets potentially linked into more
-#       than one module. In that case KBUILD_MODNAME will be set to foo_bar,
-#       where foo and bar are the name of the modules.
+# Note: Files that end up in two or more modules are compiled without the
+#       KBUILD_MODNAME definition. The reason is that any made-up name would
+#       differ in different configs.
 name-fix = $(subst $(comma),_,$(subst -,_,$1))
 basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
@@ -264,7 +264,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
        $(call cmd,dt_S_dtb)
 
 quiet_cmd_dtc = DTC     $@
-cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $<
+cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $<
 
 # Bzip2
 # ---------------------------------------------------------------------------
index 3ab316e5231336cd528b1d591c517f42860ad721..d24810fc6af6caf3a15ea3f5a55b33f4f08a667b 100755 (executable)
@@ -198,11 +198,16 @@ EOF
 }
 
 syscall_list() {
-sed -n -e '/^\#define/ s/[^_]*__NR_\([^[:space:]]*\).*/\
-\#if !defined \(__NR_\1\) \&\& !defined \(__IGNORE_\1\)\
-\#warning syscall \1 not implemented\
-\#endif/p' $1
+    grep '^[0-9]' "$1" | sort -n | (
+       while read nr abi name entry ; do
+           echo <<EOF
+#if !defined(__NR_${name}) && !defined(__IGNORE_${name})
+#warning syscall ${name} not implemented
+#endif
+EOF
+       done
+    )
 }
 
-(ignore_list && syscall_list $(dirname $0)/../arch/x86/include/asm/unistd_32.h) | \
+(ignore_list && syscall_list $(dirname $0)/../arch/x86/syscalls/syscall_32.tbl) | \
 $* -E -x c - > /dev/null
index 1bb1a1bd2daa832b234edbec3765861d4f41010d..3c2776466d877325d63b1980b798b8b0f9d6f556 100755 (executable)
@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
 #    FLAGS="-ignore_unknown_options -very_quiet"
 #    OPTIONS=$*
 
-# Workaround for Coccinelle < 0.2.3
-    FLAGS="-I $srctree/include -very_quiet"
-    shift $(( $# - 1 ))
-    OPTIONS=$1
+    if [ "$KBUILD_EXTMOD" = "" ] ; then
+        # Workaround for Coccinelle < 0.2.3
+        FLAGS="-I $srctree/include -very_quiet"
+        shift $(( $# - 1 ))
+        OPTIONS=$1
+    else
+       echo M= is not currently supported when C=1 or C=2
+       exit 1
+    fi
 else
     ONLINE=0
     FLAGS="-very_quiet"
-    OPTIONS="-dir $srctree"
+    if [ "$KBUILD_EXTMOD" = "" ] ; then
+        OPTIONS="-dir $srctree"
+    else
+        OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include"
+    fi
 fi
 
 if [ ! -x "$SPATCH" ]; then
diff --git a/scripts/coccinelle/api/devm_request_and_ioremap.cocci b/scripts/coccinelle/api/devm_request_and_ioremap.cocci
new file mode 100644 (file)
index 0000000..46beb81
--- /dev/null
@@ -0,0 +1,105 @@
+/// Reimplement a call to devm_request_mem_region followed by a call to ioremap
+/// or ioremap_nocache by a call to devm_request_and_ioremap.
+/// Devm_request_and_ioremap was introduced in
+/// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0.  It makes the code much more
+/// concise.
+///
+///
+// Confidence: High
+// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual org
+virtual report
+virtual context
+
+@nm@
+expression myname;
+identifier i;
+@@
+
+struct platform_driver i = { .driver = { .name = myname } };
+
+@depends on patch@
+expression dev,res,size;
+@@
+
+-if (!devm_request_mem_region(dev, res->start, size,
+-                              \(res->name\|dev_name(dev)\))) {
+-   ...
+-   return ...;
+-}
+... when != res->start
+(
+-devm_ioremap(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+|
+-devm_ioremap_nocache(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+)
+... when any
+    when != res->start
+
+// this rule is separate from the previous one, because a single file can
+// have multiple values of myname
+@depends on patch@
+expression dev,res,size;
+expression nm.myname;
+@@
+
+-if (!devm_request_mem_region(dev, res->start, size,myname)) {
+-   ...
+-   return ...;
+-}
+... when != res->start
+(
+-devm_ioremap(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+|
+-devm_ioremap_nocache(dev,res->start,size)
++devm_request_and_ioremap(dev,res)
+)
+... when any
+    when != res->start
+
+
+@pb depends on org || report || context@
+expression dev,res,size;
+expression nm.myname;
+position p1,p2;
+@@
+
+*if
+  (!devm_request_mem_region@p1(dev, res->start, size,
+                              \(res->name\|dev_name(dev)\|myname\))) {
+   ...
+   return ...;
+}
+... when != res->start
+(
+*devm_ioremap@p2(dev,res->start,size)
+|
+*devm_ioremap_nocache@p2(dev,res->start,size)
+)
+... when any
+    when != res->start
+
+@script:python depends on org@
+p1 << pb.p1;
+p2 << pb.p2;
+@@
+
+cocci.print_main("INFO: replace by devm_request_and_ioremap",p1)
+cocci.print_secs("",p2)
+
+@script:python depends on report@
+p1 << pb.p1;
+p2 << pb.p2;
+@@
+
+msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
index e0805ad08d39260e03e94759fde73dd85a1121e1..07a74b2c6196c0dc649aaadeee908272ed665d15 100644 (file)
@@ -1,16 +1,19 @@
 /// Use kstrdup rather than duplicating its implementation
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression from,to;
 expression flag,E1,E2;
 statement S;
@@ -23,7 +26,7 @@ statement S;
    ... when != \(from = E2 \| to = E2 \)
 -  strcpy(to, from);
 
-@@
+@depends on patch@
 expression x,from,to;
 expression flag,E1,E2,E3;
 statement S;
@@ -37,3 +40,65 @@ statement S;
     if (to==NULL || ...) S
     ... when != \(x = E3 \| from = E3 \| to = E3 \)
 -   memcpy(to, from, x);
+
+// ---------------------------------------------------------------------
+
+@r1 depends on !patch exists@
+expression from,to;
+expression flag,E1,E2;
+statement S;
+position p1,p2;
+@@
+
+*  to = kmalloc@p1(strlen(from) + 1,flag);
+   ... when != \(from = E1 \| to = E1 \)
+   if (to==NULL || ...) S
+   ... when != \(from = E2 \| to = E2 \)
+*  strcpy@p2(to, from);
+
+@r2 depends on !patch exists@
+expression x,from,to;
+expression flag,E1,E2,E3;
+statement S;
+position p1,p2;
+@@
+
+*   x = strlen(from) + 1;
+    ... when != \( x = E1 \| from = E1 \)
+*   to = \(kmalloc@p1\|kzalloc@p2\)(x,flag);
+    ... when != \(x = E2 \| from = E2 \| to = E2 \)
+    if (to==NULL || ...) S
+    ... when != \(x = E3 \| from = E3 \| to = E3 \)
+*   memcpy@p2(to, from, x);
+
+@script:python depends on org@
+p1 << r1.p1;
+p2 << r1.p2;
+@@
+
+cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_secs("strcpy",p2)
+
+@script:python depends on org@
+p1 << r2.p1;
+p2 << r2.p2;
+@@
+
+cocci.print_main("WARNING opportunity for kstrdep",p1)
+cocci.print_secs("memcpy",p2)
+
+@script:python depends on report@
+p1 << r1.p1;
+p2 << r1.p2;
+@@
+
+msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line)
+coccilib.report.print_report(p1[0], msg)
+
+@script:python depends on report@
+p1 << r2.p1;
+p2 << r2.p2;
+@@
+
+msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line)
+coccilib.report.print_report(p1[0], msg)
index b5d722077dc179fb7ba23c73215cbd701a005886..4dceab6d54de5deabae0ac3eea2aa6d00da275d8 100644 (file)
@@ -1,14 +1,17 @@
 /// Use kmemdup rather than duplicating its implementation
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
 @r1@
 expression from,to;
@@ -28,7 +31,7 @@ position p;
     ... when != \( x = E1 \| from = E1 \)
     to = \(kmalloc@p\|kzalloc@p\)(x,flag);
 
-@@
+@depends on patch@
 expression from,to,size,flag;
 position p != {r1.p,r2.p};
 statement S;
@@ -38,3 +41,26 @@ statement S;
 +  to = kmemdup(from,size,flag);
    if (to==NULL || ...) S
 -  memcpy(to, from, size);
+
+@r depends on !patch@
+expression from,to,size,flag;
+position p != {r1.p,r2.p};
+statement S;
+@@
+
+*  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+   to = kmemdup(from,size,flag);
+   if (to==NULL || ...) S
+*  memcpy(to, from, size);
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep")
index 72ce012e878a12bbcdcf83f421ac885751763ddf..2efac289fd59d2beb755593acdd0c6fc39f3ec61 100644 (file)
@@ -1,23 +1,25 @@
-/// Use kmemdup_user rather than duplicating its implementation
+/// Use memdup_user rather than duplicating its implementation
 /// This is a little bit restricted to reduce false positives
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression from,to,size,flag;
-position p;
 identifier l1,l2;
 @@
 
--  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+-  to = \(kmalloc\|kzalloc\)(size,flag);
 +  to = memdup_user(from,size);
    if (
 -      to==NULL
@@ -33,3 +35,26 @@ identifier l1,l2;
 -    -EFAULT
 -    ...+>
 -  }
+
+@r depends on !patch@
+expression from,to,size,flag;
+position p;
+statement S1,S2;
+@@
+
+*  to = \(kmalloc@p\|kzalloc@p\)(size,flag);
+   if (to==NULL || ...) S1
+   if (copy_from_user(to, from, size) != 0)
+   S2
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user")
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
new file mode 100644 (file)
index 0000000..0a1e361
--- /dev/null
@@ -0,0 +1,71 @@
+/// Find uses of standard freeing functons on values allocated using devm_
+/// functions.  Values allocated using the devm_functions are freed when
+/// the device is detached, and thus the use of the standard freeing
+/// function would cause a double free.
+/// See Documentation/driver-model/devres.txt for more information.
+///
+/// A difficulty of detecting this problem is that the standard freeing
+/// function might be called from a different function than the one
+/// containing the allocation function.  It is thus necessary to make the
+/// connection between the allocation function and the freeing function.
+/// Here this is done using the specific argument text, which is prone to
+/// false positives.  There is no rule for the request_region and
+/// request_mem_region variants because this heuristic seems to be a bit
+/// less reliable in these cases.
+///
+// Confidence: Moderate
+// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual org
+virtual report
+virtual context
+
+@r depends on context || org || report@
+expression x;
+@@
+
+(
+ x = devm_kzalloc(...)
+|
+ x = devm_request_irq(...)
+|
+ x = devm_ioremap(...)
+|
+ x = devm_ioremap_nocache(...)
+|
+ x = devm_ioport_map(...)
+)
+
+@pb@
+expression r.x;
+position p;
+@@
+
+(
+* kfree@p(x)
+|
+* free_irq@p(x)
+|
+* iounmap@p(x)
+|
+* ioport_unmap@p(x)
+)
+
+@script:python depends on org@
+p << pb.p;
+@@
+
+msg="WARNING: invalid free of devm_ allocated data"
+coccilib.org.print_todo(p[0], msg)
+
+@script:python depends on report@
+p << pb.p;
+@@
+
+msg="WARNING: invalid free of devm_ allocated data"
+coccilib.report.print_report(p[0], msg)
+
index f9f79d9245ee9815ef3e244f791553501e1391b2..d9ae6d89c2f57e9db00a856f461b1f968cf07018 100644 (file)
@@ -5,9 +5,9 @@
 //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
@@ -23,7 +23,7 @@ position p1;
 kfree@p1(E)
 
 @print expression@
-constant char *c;
+constant char [] c;
 expression free.E,E2;
 type T;
 position p;
@@ -36,6 +36,10 @@ identifier f;
  E@p == E2
 |
  E@p != E2
+|
+ E2 == E@p
+|
+ E2 != E@p
 |
  !E@p
 |
@@ -113,5 +117,5 @@ p1 << free.p1;
 p2 << r.p2;
 @@
 
-msg = "reference preceded by free on line %s" % (p1[0].line)
+msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
 coccilib.report.print_report(p2[0],msg)
index 77bc108c3f597b715850465c0a5fa26333132bec..0a40af828c43a4161b94d2b9c85a66830ae60f1b 100644 (file)
@@ -2,16 +2,19 @@
 /// is no point to call of_node_put on the final value.
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 iterator name for_each_node_by_name;
 expression np,E;
 identifier l;
@@ -24,7 +27,7 @@ for_each_node_by_name(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_node_by_type;
 expression np,E;
 identifier l;
@@ -37,7 +40,7 @@ for_each_node_by_type(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_compatible_node;
 expression np,E;
 identifier l;
@@ -50,7 +53,7 @@ for_each_compatible_node(np,...) {
 ... when != np = E
 - of_node_put(np);
 
-@@
+@depends on patch@
 iterator name for_each_matching_node;
 expression np,E;
 identifier l;
@@ -62,3 +65,59 @@ for_each_matching_node(np,...) {
 }
 ... when != np = E
 - of_node_put(np);
+
+// ----------------------------------------------------------------------
+
+@r depends on !patch forall@
+//iterator name for_each_node_by_name;
+//iterator name for_each_node_by_type;
+//iterator name for_each_compatible_node;
+//iterator name for_each_matching_node;
+expression np,E;
+identifier l;
+position p1,p2;
+@@
+
+(
+*for_each_node_by_name@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_node_by_type@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_compatible_node@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+|
+*for_each_matching_node@p1(np,...)
+{
+  ... when != break;
+      when != goto l;
+}
+)
+... when != np = E
+* of_node_put@p2(np);
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("unneeded of_node_put",p2)
+cocci.print_secs("iterator",p1)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index baa4297a4ed18d6ae757b10404dcdcefb88d7892..259899f6838edaa463d16d445e7f7b8f39d132f6 100644 (file)
@@ -1,20 +1,24 @@
 /// Many iterators have the property that the first argument is always bound
-/// to a real list element, never NULL.  False positives arise for some
-/// iterators that do not have this property, or in cases when the loop
-/// cursor is reassigned.  The latter should only happen when the matched
-/// code is on the way to a loop exit (break, goto, or return).
+/// to a real list element, never NULL.
+//# False positives arise for some iterators that do not have this property,
+//# or in cases when the loop cursor is reassigned.  The latter should only
+//# happen when the matched code is on the way to a loop exit (break, goto,
+//# or return).
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 iterator I;
 expression x,E,E1,E2;
 statement S,S1,S2;
@@ -55,4 +59,36 @@ I(x,...) { <...
   x != NULL
 + )
 )
-  ...> }
\ No newline at end of file
+  ...> }
+
+@r depends on !patch exists@
+iterator I;
+expression x,E;
+position p1,p2;
+@@
+
+*I@p1(x,...)
+{ ... when != x = E
+(
+*  x@p2 == NULL
+|
+*  x@p2 != NULL
+)
+  ... when any
+}
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("iterator-bound variable",p1)
+cocci.print_secs("useless NULL test",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index 00af5344a68f2a1269b85e093bc25ddc56e0f98e..8f10b49603c32e11b9c0aa2845da8f11d7901f5e 100644 (file)
@@ -1,17 +1,20 @@
 /// Find functions that refer to GFP_KERNEL but are called with locks held.
-/// The proposed change of converting the GFP_KERNEL is not necessarily the
-/// correct one.  It may be desired to unlock the lock, or to not call the
-/// function under the lock in the first place.
+//# The proposed change of converting the GFP_KERNEL is not necessarily the
+//# correct one.  It may be desired to unlock the lock, or to not call the
+//# function under the lock in the first place.
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
 @gfp exists@
 identifier fn;
@@ -32,28 +35,29 @@ fn(...) {
  ... when any
 }
 
-@locked@
+@locked exists@
 identifier gfp.fn;
+position p1,p2;
 @@
 
 (
-read_lock_irq
+read_lock_irq@p1
 |
-write_lock_irq
+write_lock_irq@p1
 |
-read_lock_irqsave
+read_lock_irqsave@p1
 |
-write_lock_irqsave
+write_lock_irqsave@p1
 |
-spin_lock
+spin_lock@p1
 |
-spin_trylock
+spin_trylock@p1
 |
-spin_lock_irq
+spin_lock_irq@p1
 |
-spin_lock_irqsave
+spin_lock_irqsave@p1
 |
-local_irq_disable
+local_irq_disable@p1
 )
  (...)
 ...  when != read_unlock_irq(...)
@@ -64,11 +68,38 @@ local_irq_disable
      when != spin_unlock_irq(...)
      when != spin_unlock_irqrestore(...)
      when != local_irq_enable(...)
-fn(...)
+fn@p2(...)
 
-@depends on locked@
+@depends on locked && patch@
 position gfp.p;
 @@
 
 - GFP_KERNEL@p
 + GFP_ATOMIC
+
+@depends on locked && !patch@
+position gfp.p;
+@@
+
+* GFP_KERNEL@p
+
+@script:python depends on !patch && org@
+p << gfp.p;
+fn << gfp.fn;
+p1 << locked.p1;
+p2 << locked.p2;
+@@
+
+cocci.print_main("lock",p1)
+cocci.print_secs("call",p2)
+cocci.print_secs("GFP_KERNEL",p)
+
+@script:python depends on !patch && report@
+p << gfp.p;
+fn << gfp.fn;
+p1 << locked.p1;
+p2 << locked.p2;
+@@
+
+msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line)
+coccilib.report.print_report(p[0], msg)
index b4344d838097bb4a541fbd15097d7ef81367bc02..1c4ffe6fd846746d64a1a34168fb3864f18b9af8 100644 (file)
@@ -1,9 +1,9 @@
 /// Find nested lock+irqsave functions that use the same flags variables
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
@@ -12,7 +12,7 @@ virtual context
 virtual org
 virtual report
 
-@r@
+@r exists@
 expression lock1,lock2,flags;
 position p1,p2;
 @@
@@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags)
 write_lock_irqsave@p2(lock2,flags)
 )
 
-@d@
+@d exists@
 expression f <= r.flags;
 expression lock1,lock2,flags;
 position r.p1, r.p2;
@@ -76,5 +76,5 @@ p1 << r.p1;
 p2 << r.p2;
 @@
 
-msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line)
+msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line)
 coccilib.report.print_report(p2[0], msg)
index 7641a2925434219ec314d3c3718b80908b77ff5c..3267d7410bd5072aaab32efd8d5e4c4f06205618 100644 (file)
@@ -6,13 +6,14 @@
 /// function call that releases the lock.
 ///
 // Confidence: Moderate
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
+virtual context
 virtual org
 virtual report
 
@@ -57,7 +58,7 @@ position r;
 
 for(...;...;...) { <+... return@r ...; ...+> }
 
-@err@
+@err exists@
 expression E1;
 position prelocked.p;
 position up != prelocked.p1;
@@ -65,14 +66,14 @@ position r!=looped.r;
 identifier lock,unlock;
 @@
 
-lock(E1@p,...);
+*lock(E1@p,...);
 <+... when != E1
 if (...) {
   ... when != E1
-  return@r ...;
+*  return@r ...;
 }
 ...+>
-unlock@up(E1,...);
+*unlock@up(E1,...);
 
 @script:python depends on org@
 p << prelocked.p1;
index 156b20adb35163a603a533a90d73d7a7cc6c6ad0..cf74a00cf59740d51f828f3140460f77268c1d40 100644 (file)
@@ -3,9 +3,9 @@
 /// initialization.
 ///
 // Confidence: Low
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
 // Options: -no_includes -include_headers
@@ -49,5 +49,5 @@ pr << r.p;
 @@
 
 if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
-  msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line)
+  msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
   coccilib.report.print_report(p0[0],msg)
index 4c9c52b9c41331c87d2b532b0439ea316a3cba24..ed961a1f7d11b28c8e9581e4bffa43edaa495a5b 100644 (file)
@@ -1,16 +1,19 @@
 /// The various basic memory allocation functions don't return ERR_PTR
 ///
 // Confidence: High
-// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
-// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
-// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
 // URL: http://coccinelle.lip6.fr/
 // Comments:
 // Options: -no_includes -include_headers
 
 virtual patch
+virtual context
+virtual org
+virtual report
 
-@@
+@depends on patch@
 expression x,E;
 @@
 
@@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache
 ... when != x = E
 - IS_ERR(x)
 + !x
+
+@r depends on !patch exists@
+expression x,E;
+position p1,p2;
+@@
+
+*x = \(kmalloc@p1\|kzalloc@p1\|kcalloc@p1\|kmem_cache_alloc@p1\|kmem_cache_zalloc@p1\|kmem_cache_alloc_node@p1\|kmalloc_node@p1\|kzalloc_node@p1\)(...)
+... when != x = E
+* IS_ERR@p2(x)
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("alloc call",p1)
+cocci.print_secs("IS_ERR that should be NULL tests",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
index cbc0193098e4e83ea4628facb1d86dcbcc54be18..451c92d31b196634cfb9ed7b2b15c632efd89691 100644 (file)
@@ -71,6 +71,7 @@ static void  __attribute__ ((noreturn)) usage(void)
        fprintf(stderr, "\t\t\tasm - assembler source\n");
        fprintf(stderr, "\t-V <output version>\n");
        fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
+       fprintf(stderr, "\t-d <output dependency file>\n");
        fprintf(stderr, "\t-R <number>\n");
        fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
        fprintf(stderr, "\t-S <bytes>\n");
@@ -99,6 +100,7 @@ int main(int argc, char *argv[])
        const char *inform = "dts";
        const char *outform = "dts";
        const char *outname = "-";
+       const char *depname = NULL;
        int force = 0, check = 0, sort = 0;
        const char *arg;
        int opt;
@@ -111,7 +113,8 @@ int main(int argc, char *argv[])
        minsize    = 0;
        padsize    = 0;
 
-       while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:s")) != EOF) {
+       while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
+                       != EOF) {
                switch (opt) {
                case 'I':
                        inform = optarg;
@@ -125,6 +128,9 @@ int main(int argc, char *argv[])
                case 'V':
                        outversion = strtol(optarg, NULL, 0);
                        break;
+               case 'd':
+                       depname = optarg;
+                       break;
                case 'R':
                        reservenum = strtol(optarg, NULL, 0);
                        break;
@@ -188,6 +194,14 @@ int main(int argc, char *argv[])
        fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
                inform, outform, arg);
 
+       if (depname) {
+               depfile = fopen(depname, "w");
+               if (!depfile)
+                       die("Couldn't open dependency file %s: %s\n", depname,
+                           strerror(errno));
+               fprintf(depfile, "%s:", outname);
+       }
+
        if (streq(inform, "dts"))
                bi = dt_from_source(arg);
        else if (streq(inform, "fs"))
@@ -197,6 +211,11 @@ int main(int argc, char *argv[])
        else
                die("Unknown input format \"%s\"\n", inform);
 
+       if (depfile) {
+               fputc('\n', depfile);
+               fclose(depfile);
+       }
+
        if (cmdline_boot_cpuid != -1)
                bi->boot_cpuid_phys = cmdline_boot_cpuid;
 
index 2dbc874288ca1b7487dd423d630cb7ac3b63e50f..36a38e9f1a2cb9200ee07bfce22eab489f1f1127 100644 (file)
@@ -40,6 +40,7 @@ static char *dirname(const char *path)
        return NULL;
 }
 
+FILE *depfile; /* = NULL */
 struct srcfile_state *current_srcfile; /* = NULL */
 
 /* Detect infinite include recursion. */
@@ -67,6 +68,9 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
                            strerror(errno));
        }
 
+       if (depfile)
+               fprintf(depfile, " %s", fullname);
+
        if (fullnamep)
                *fullnamep = fullname;
        else
index bd7966e56a53672f8c5c34369067c38696e9e246..ce980cafe58867d64d7a142b00914034f24f0d50 100644 (file)
@@ -30,6 +30,7 @@ struct srcfile_state {
        struct srcfile_state *prev;
 };
 
+extern FILE *depfile; /* = NULL */
 extern struct srcfile_state *current_srcfile; /* = NULL */
 
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
index a5510903e874a35a5cbb238e1eb50a7b82746fd6..aca33b98bf634b269b9857f5bc08d2e315f5f8d3 100644 (file)
@@ -11,3 +11,4 @@ HOSTCFLAGS_lex.lex.o := -I$(src)
 # dependencies on generated files need to be listed explicitly
 $(obj)/lex.lex.o: $(obj)/keywords.hash.c $(obj)/parse.tab.h
 
+clean-files    := keywords.hash.c lex.lex.c parse.tab.c parse.tab.h
index 914833d99b06f78242fa12584c568ecef6a5e65a..79662658fb9158af1d7b3ee43dba0cfab0aa42cf 100644 (file)
@@ -50,9 +50,8 @@ localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
 
 # Create new linux.pot file
 # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
-# The symlink is used to repair a deficiency in arch/um
 update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
-       $(Q)echo "  GEN config"
+       $(Q)echo "  GEN     config.pot"
        $(Q)xgettext --default-domain=linux                         \
            --add-comments --keyword=_ --keyword=N_                 \
            --from-code=UTF-8                                       \
@@ -63,10 +62,11 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
        $(Q)(for i in `ls $(srctree)/arch/*/Kconfig      \
            $(srctree)/arch/*/um/Kconfig`;               \
            do                                           \
-               echo "  GEN $$i";                        \
+               echo "  GEN     $$i";                    \
                $(obj)/kxgettext $$i                     \
                     >> $(obj)/config.pot;               \
            done )
+       $(Q)echo "  GEN     linux.pot"
        $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
            --output $(obj)/linux.pot
        $(Q)rm -f $(obj)/config.pot
index 5a58965d8800daab99a8bd096262c1f95465482d..7c7a5a6cc3f504bd759dc01019536b2bf804fbbd 100644 (file)
@@ -464,7 +464,7 @@ kconfig_print_comment(FILE *fp, const char *value, void *arg)
                fprintf(fp, "#");
                if (l) {
                        fprintf(fp, " ");
-                       fwrite(p, l, 1, fp);
+                       xfwrite(p, l, 1, fp);
                        p += l;
                }
                fprintf(fp, "\n");
@@ -537,7 +537,7 @@ header_print_comment(FILE *fp, const char *value, void *arg)
                fprintf(fp, " *");
                if (l) {
                        fprintf(fp, " ");
-                       fwrite(p, l, 1, fp);
+                       xfwrite(p, l, 1, fp);
                        p += l;
                }
                fprintf(fp, "\n");
index 80fce57080cc36787e01efc00fe8a111efa3d0ff..d4ecce8bc3a689daa2157e4f47e65e7c62192bd4 100644 (file)
@@ -10,6 +10,7 @@
 extern "C" {
 #endif
 
+#include <assert.h>
 #include <stdio.h>
 #ifndef __cplusplus
 #include <stdbool.h>
index 9f4438027df4201b9fb34d4191cdb3da9ac4994f..adc230638c5b141ceaa2cf9b25d35f99324c19b6 100644 (file)
@@ -683,7 +683,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_MESSAGE_INFO,
-                                       GTK_BUTTONS_CLOSE, intro_text);
+                                       GTK_BUTTONS_CLOSE, "%s", intro_text);
        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                                 G_CALLBACK(gtk_widget_destroy),
                                 GTK_OBJECT(dialog));
@@ -701,7 +701,7 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_MESSAGE_INFO,
-                                       GTK_BUTTONS_CLOSE, about_text);
+                                       GTK_BUTTONS_CLOSE, "%s", about_text);
        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                                 G_CALLBACK(gtk_widget_destroy),
                                 GTK_OBJECT(dialog));
@@ -720,7 +720,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_MESSAGE_INFO,
-                                       GTK_BUTTONS_CLOSE, license_text);
+                                       GTK_BUTTONS_CLOSE, "%s", license_text);
        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                                 G_CALLBACK(gtk_widget_destroy),
                                 GTK_OBJECT(dialog));
@@ -830,7 +830,7 @@ static void renderer_edited(GtkCellRendererText * cell,
 static void change_sym_value(struct menu *menu, gint col)
 {
        struct symbol *sym = menu->sym;
-       tristate oldval, newval;
+       tristate newval;
 
        if (!sym)
                return;
@@ -847,7 +847,6 @@ static void change_sym_value(struct menu *menu, gint col)
        switch (sym_get_type(sym)) {
        case S_BOOLEAN:
        case S_TRISTATE:
-               oldval = sym_get_tristate_value(sym);
                if (!sym_tristate_within_range(sym, newval))
                        newval = yes;
                sym_set_tristate_value(sym, newval);
@@ -1278,7 +1277,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
        gboolean valid;
        GtkTreeIter *sibling;
        struct symbol *sym;
-       struct property *prop;
        struct menu *menu1, *menu2;
 
        if (src == &rootmenu)
@@ -1287,7 +1285,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
        valid = gtk_tree_model_iter_children(model2, child2, dst);
        for (child1 = src->list; child1; child1 = child1->next) {
 
-               prop = child1->prompt;
                sym = child1->sym;
 
              reparse:
index b633bdb9f3d47c815be8727b155471167135626a..c18f2bd9c095510d1d5e58575b265bd67ae9e781 100644 (file)
@@ -90,8 +90,10 @@ struct conf_printer {
 /* confdata.c and expr.c */
 static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
 {
-       if (fwrite(str, len, count, out) < count)
-               fprintf(stderr, "\nError in writing or end of file.\n");
+       assert(len != 0);
+
+       if (fwrite(str, len, count, out) != count)
+               fprintf(stderr, "Error in writing or end of file.\n");
 }
 
 /* menu.c */
index 19e200d9112091fc3ddfe5aac59f94b32b38c4dc..2c6286c0bc1ac70ef190bdbd031905593070c933 100644 (file)
@@ -830,6 +830,8 @@ static int handle_exit(void)
                fprintf(stderr, _("\n\n"
                                  "Your configuration changes were NOT saved."
                                  "\n\n"));
+               if (res != KEY_ESC)
+                       res = 0;
        }
 
        return res;
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
new file mode 100644 (file)
index 0000000..ceadf0e
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/sh
+#  merge_config.sh - Takes a list of config fragment values, and merges
+#  them one by one. Provides warnings on overridden values, and specified
+#  values that did not make it to the resulting .config file (due to missed
+#  dependencies or config symbol removal).
+#
+#  Portions reused from kconf_check and generate_cfg:
+#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
+#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
+#
+#  Copyright (c) 2009-2010 Wind River Systems, Inc.
+#  Copyright 2011 Linaro
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License version 2 as
+#  published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU General Public License for more details.
+
+clean_up() {
+       rm -f $TMP_FILE
+       exit
+}
+trap clean_up HUP INT TERM
+
+usage() {
+       echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
+       echo "  -h    display this help text"
+       echo "  -m    only merge the fragments, do not execute the make command"
+       echo "  -n    use allnoconfig instead of alldefconfig"
+}
+
+MAKE=true
+ALLTARGET=alldefconfig
+
+while true; do
+       case $1 in
+       "-n")
+               ALLTARGET=allnoconfig
+               shift
+               continue
+               ;;
+       "-m")
+               MAKE=false
+               shift
+               continue
+               ;;
+       "-h")
+               usage
+               exit
+               ;;
+       *)
+               break
+               ;;
+       esac
+done
+
+
+
+MERGE_LIST=$*
+SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
+TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+
+# Merge files, printing warnings on overrided values
+for MERGE_FILE in $MERGE_LIST ; do
+       echo "Merging $MERGE_FILE"
+       CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
+
+       for CFG in $CFG_LIST ; do
+               grep -q -w $CFG $TMP_FILE
+               if [ $? -eq 0 ] ; then
+                       PREV_VAL=$(grep -w $CFG $TMP_FILE)
+                       NEW_VAL=$(grep -w $CFG $MERGE_FILE)
+                       if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
+                       echo Value of $CFG is redefined by fragment $MERGE_FILE:
+                       echo Previous  value: $PREV_VAL
+                       echo New value:       $NEW_VAL
+                       echo
+                       fi
+                       sed -i "/$CFG[ =]/d" $TMP_FILE
+               fi
+       done
+       cat $MERGE_FILE >> $TMP_FILE
+done
+
+if [ "$MAKE" = "false" ]; then
+       cp $TMP_FILE .config
+       echo "#"
+       echo "# merged configuration written to .config (needs make)"
+       echo "#"
+       clean_up
+       exit
+fi
+
+# Use the merged file as the starting point for:
+# alldefconfig: Fills in any missing symbols with Kconfig default
+# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
+make KCONFIG_ALLCONFIG=$TMP_FILE $ALLTARGET
+
+
+# Check all specified config values took (might have missed-dependency issues)
+for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
+
+       REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
+       ACTUAL_VAL=$(grep -w -e "$CFG" .config)
+       if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
+               echo "Value requested for $CFG not in final .config"
+               echo "Requested value:  $REQUESTED_VAL"
+               echo "Actual value:     $ACTUAL_VAL"
+               echo ""
+       fi
+done
+
+clean_up
index 38f6617a2cb16c614a2ed0a854eb97b7aa12cdbb..833813a99e7c23a29c4e7147c58ac0ca2c696400 100755 (executable)
@@ -132,7 +132,28 @@ exuberant()
        --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/'        \
        --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
        --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'               \
-       --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/'
+       --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/'     \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/'                     \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/'                  \
+       --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/'                \
+       --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/'           \
+       --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/'                 \
+       --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/'               \
+       --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/'           \
+       --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'       \
+       --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'     \
+       --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/'           \
+       --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/'       \
+       --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/'              \
+       --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/'            \
+       --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/'               \
+       --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/'            \
+       --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/'          \
+       --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/'          \
+       --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/'      \
+       --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/'  \
+       --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
+       --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
@@ -146,6 +167,8 @@ exuberant()
        --langdef=dotconfig --language-force=dotconfig          \
        --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'
 
+       # Remove structure forward declarations.
+       LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags
 }
 
 emacs()
@@ -154,7 +177,28 @@ emacs()
        --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/'            \
        --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/'   \
        --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/'          \
-       --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/'
+       --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \
+       --regex='/PAGEFLAG\(([^,)]*).*/Page\1/'                 \
+       --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/'              \
+       --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/'            \
+       --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/'       \
+       --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/'             \
+       --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/'           \
+       --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/'       \
+       --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/'   \
+       --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
+       --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/'       \
+       --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/'   \
+       --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/'          \
+       --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/'        \
+       --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/'           \
+       --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/'        \
+       --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/'      \
+       --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/'      \
+       --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/'  \
+       --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
+       --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
+       --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
index ad409381f8cca21370f4802b1a5044af2f946b71..b413ed05e74deae78fbd97809c99f0fd68f1ee46 100644 (file)
@@ -12,6 +12,9 @@ config SND_HWDEP
 config SND_RAWMIDI
        tristate
 
+config SND_COMPRESS_OFFLOAD
+       tristate
+
 # To be effective this also requires INPUT - users should say:
 #    select SND_JACK if INPUT=y || INPUT=SND
 # to avoid having to force INPUT on.
@@ -154,16 +157,6 @@ config SND_DYNAMIC_MINORS
 
          If you are unsure about this, say N here.
 
-config SND_COMPRESS_OFFLOAD
-       tristate "ALSA Compressed audio offload support"
-       default n
-       help
-         If you want support for offloading compressed audio and have such
-         a hardware, then you should say Y here and also to the DSP driver
-         of your platform.
-
-         If you are unsure about this, say N here.
-
 config SND_SUPPORT_OLD_API
        bool "Support old ALSA API"
        default y
index 762bb108c51c139b71e93cf8d627ebae858a25d2..f13ad536b2d59fe19ab9826b5abc0c301d5133cf 100644 (file)
@@ -268,8 +268,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                card->shortname, chip->io, chip->irq);
 
        // (4) Alloc components.
+       err = snd_vortex_mixer(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
        // ADB pcm.
-       if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
+       err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
+       if (err < 0) {
                snd_card_free(card);
                return err;
        }
@@ -299,11 +305,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return err;
        }
 #endif
-       // snd_ac97_mixer and Vortex mixer.
-       if ((err = snd_vortex_mixer(chip)) < 0) {
-               snd_card_free(card);
-               return err;
-       }
        if ((err = snd_vortex_midi(chip)) < 0) {
                snd_card_free(card);
                return err;
index 02f6e08f7592e8bcd6c539598f397ebbf88856aa..bb938153a964811b41f471f064fbd293fb660e77 100644 (file)
 #define MIX_SPDIF(x) (vortex->mixspdif[x])
 
 #define NR_WTPB 0x20           /* WT channels per each bank. */
+#define NR_PCM 0x10
 
 /* Structs */
 typedef struct {
index 0488633ea87474c608591601201030a65a1c91f5..0ef2f97122080f206699a01e32b7f1f1ce7b6825 100644 (file)
@@ -168,6 +168,7 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
                        runtime->hw = snd_vortex_playback_hw_adb;
 #ifdef CHIP_AU8830
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+                       VORTEX_IS_QUAD(vortex) &&
                        VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
                        runtime->hw.channels_max = 4;
                        snd_pcm_hw_constraint_list(runtime, 0,
index 0852e204a4c8439e557bd553dcde3aae1f7c173a..fb35474c1203658fb137b650da9dec0b3b1876ad 100644 (file)
@@ -2498,6 +2498,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
index 87e684fa830f83df49bfec3aa5e894d8c97bfa07..3556408d6ece45236ff5b13217f5f7d29905c6cc 100644 (file)
@@ -1596,7 +1596,7 @@ static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
                                "Dell Studio 1557", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
-                               "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+                               "Dell Studio XPS 1645", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
                                "Dell Studio 1558", STAC_DELL_M6_DMIC),
        {} /* terminator */
index 478303e6c2b0801c16c2ae52ee4eff0996fac472..63cff90706bf1749b9b7154f1c6ec81c903f68fd 100644 (file)
@@ -177,6 +177,7 @@ static void wm8776_registers_init(struct oxygen *chip)
        struct xonar_wm87x6 *data = chip->model_data;
 
        wm8776_write(chip, WM8776_RESET, 0);
+       wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
        wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
                     WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
        wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
index 45d11ddaeea9110a66182eaaa18047c8465ff90b..946020a647db2e1d5eec71f82fb9a3c936ced546 100644 (file)
@@ -366,7 +366,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
                goto out3;
 
        /* enbale ac97 multifunction pin */
-       mfp_set_groupg(nuc900_audio->dev, "nuc900-audio");
+       mfp_set_groupg(nuc900_audio->dev, NULL);
 
        return 0;
 
index 9a571e71683c2dfea90ddcf03911d93abee75081..a373a5bfff683cc4b395588af358a2aa92b2171d 100755 (executable)
@@ -2,7 +2,9 @@
 
 open (IN,"ktest.pl");
 while (<IN>) {
+    # hashes are now used
     if (/\$opt\{"?([A-Z].*?)(\[.*\])?"?\}/ ||
+       /^\s*"?([A-Z].*?)"?\s*=>\s*/ ||
        /set_test_option\("(.*?)"/) {
        $opt{$1} = 1;
     }
@@ -11,7 +13,7 @@ close IN;
 
 open (IN, "sample.conf");
 while (<IN>) {
-    if (/^\s*#?\s*(\S+)\s*=/) {
+    if (/^\s*#?\s*([A-Z]\S*)\s*=/) {
        $samp{$1} = 1;
     }
 }
index 8b4c2535b266a2abe17d3ad495b3a0fdfa8855a9..62a134dc421ae37d14307a44f09abc9c0d0c197a 100755 (executable)
@@ -18,40 +18,50 @@ $| = 1;
 my %opt;
 my %repeat_tests;
 my %repeats;
-my %default;
 
 #default opts
-$default{"NUM_TESTS"}          = 1;
-$default{"REBOOT_TYPE"}                = "grub";
-$default{"TEST_TYPE"}          = "test";
-$default{"BUILD_TYPE"}         = "randconfig";
-$default{"MAKE_CMD"}           = "make";
-$default{"TIMEOUT"}            = 120;
-$default{"TMP_DIR"}            = "/tmp/ktest/\${MACHINE}";
-$default{"SLEEP_TIME"}         = 60;   # sleep time between tests
-$default{"BUILD_NOCLEAN"}      = 0;
-$default{"REBOOT_ON_ERROR"}    = 0;
-$default{"POWEROFF_ON_ERROR"}  = 0;
-$default{"REBOOT_ON_SUCCESS"}  = 1;
-$default{"POWEROFF_ON_SUCCESS"}        = 0;
-$default{"BUILD_OPTIONS"}      = "";
-$default{"BISECT_SLEEP_TIME"}  = 60;   # sleep time between bisects
-$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
-$default{"CLEAR_LOG"}          = 0;
-$default{"BISECT_MANUAL"}      = 0;
-$default{"BISECT_SKIP"}                = 1;
-$default{"SUCCESS_LINE"}       = "login:";
-$default{"DETECT_TRIPLE_FAULT"} = 1;
-$default{"NO_INSTALL"}         = 0;
-$default{"BOOTED_TIMEOUT"}     = 1;
-$default{"DIE_ON_FAILURE"}     = 1;
-$default{"SSH_EXEC"}           = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
-$default{"SCP_TO_TARGET"}      = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
-$default{"REBOOT"}             = "ssh \$SSH_USER\@\$MACHINE reboot";
-$default{"STOP_AFTER_SUCCESS"} = 10;
-$default{"STOP_AFTER_FAILURE"} = 60;
-$default{"STOP_TEST_AFTER"}    = 600;
-$default{"LOCALVERSION"}       = "-test";
+my %default = (
+    "NUM_TESTS"                        => 1,
+    "TEST_TYPE"                        => "build",
+    "BUILD_TYPE"               => "randconfig",
+    "MAKE_CMD"                 => "make",
+    "TIMEOUT"                  => 120,
+    "TMP_DIR"                  => "/tmp/ktest/\${MACHINE}",
+    "SLEEP_TIME"               => 60,  # sleep time between tests
+    "BUILD_NOCLEAN"            => 0,
+    "REBOOT_ON_ERROR"          => 0,
+    "POWEROFF_ON_ERROR"                => 0,
+    "REBOOT_ON_SUCCESS"                => 1,
+    "POWEROFF_ON_SUCCESS"      => 0,
+    "BUILD_OPTIONS"            => "",
+    "BISECT_SLEEP_TIME"                => 60,   # sleep time between bisects
+    "PATCHCHECK_SLEEP_TIME"    => 60, # sleep time between patch checks
+    "CLEAR_LOG"                        => 0,
+    "BISECT_MANUAL"            => 0,
+    "BISECT_SKIP"              => 1,
+    "SUCCESS_LINE"             => "login:",
+    "DETECT_TRIPLE_FAULT"      => 1,
+    "NO_INSTALL"               => 0,
+    "BOOTED_TIMEOUT"           => 1,
+    "DIE_ON_FAILURE"           => 1,
+    "SSH_EXEC"                 => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
+    "SCP_TO_TARGET"            => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
+    "REBOOT"                   => "ssh \$SSH_USER\@\$MACHINE reboot",
+    "STOP_AFTER_SUCCESS"       => 10,
+    "STOP_AFTER_FAILURE"       => 60,
+    "STOP_TEST_AFTER"          => 600,
+
+# required, and we will ask users if they don't have them but we keep the default
+# value something that is common.
+    "REBOOT_TYPE"              => "grub",
+    "LOCALVERSION"             => "-test",
+    "SSH_USER"                 => "root",
+    "BUILD_TARGET"             => "arch/x86/boot/bzImage",
+    "TARGET_IMAGE"             => "/boot/vmlinuz-test",
+
+    "LOG_FILE"                 => undef,
+    "IGNORE_UNUSED"            => 0,
+);
 
 my $ktest_config;
 my $version;
@@ -73,6 +83,8 @@ my $reboot_script;
 my $power_cycle;
 my $reboot;
 my $reboot_on_error;
+my $switch_to_good;
+my $switch_to_test;
 my $poweroff_on_error;
 my $die_on_failure;
 my $powercycle_after_reboot;
@@ -92,17 +104,24 @@ my $start_minconfig;
 my $start_minconfig_defined;
 my $output_minconfig;
 my $ignore_config;
+my $ignore_errors;
 my $addconfig;
 my $in_bisect = 0;
-my $bisect_bad = "";
+my $bisect_bad_commit = "";
 my $reverse_bisect;
 my $bisect_manual;
 my $bisect_skip;
 my $config_bisect_good;
+my $bisect_ret_good;
+my $bisect_ret_bad;
+my $bisect_ret_skip;
+my $bisect_ret_abort;
+my $bisect_ret_default;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
 my $buildlog;
+my $testlog;
 my $dmesg;
 my $monitor_fp;
 my $monitor_pid;
@@ -112,6 +131,7 @@ my $bisect_sleep_time;
 my $patchcheck_sleep_time;
 my $ignore_warnings;
 my $store_failures;
+my $store_successes;
 my $test_name;
 my $timeout;
 my $booted_timeout;
@@ -124,10 +144,34 @@ my $stop_after_failure;
 my $stop_test_after;
 my $build_target;
 my $target_image;
+my $checkout;
 my $localversion;
 my $iteration = 0;
 my $successes = 0;
 
+my $bisect_good;
+my $bisect_bad;
+my $bisect_type;
+my $bisect_start;
+my $bisect_replay;
+my $bisect_files;
+my $bisect_reverse;
+my $bisect_check;
+
+my $config_bisect;
+my $config_bisect_type;
+
+my $patchcheck_type;
+my $patchcheck_start;
+my $patchcheck_end;
+
+# set when a test is something other that just building or install
+# which would require more options.
+my $buildonly = 1;
+
+# set when creating a new config
+my $newconfig = 0;
+
 my %entered_configs;
 my %config_help;
 my %variable;
@@ -136,11 +180,99 @@ my %force_config;
 # do not force reboots on config problems
 my $no_reboot = 1;
 
+my %option_map = (
+    "MACHINE"                  => \$machine,
+    "SSH_USER"                 => \$ssh_user,
+    "TMP_DIR"                  => \$tmpdir,
+    "OUTPUT_DIR"               => \$outputdir,
+    "BUILD_DIR"                        => \$builddir,
+    "TEST_TYPE"                        => \$test_type,
+    "BUILD_TYPE"               => \$build_type,
+    "BUILD_OPTIONS"            => \$build_options,
+    "PRE_BUILD"                        => \$pre_build,
+    "POST_BUILD"               => \$post_build,
+    "PRE_BUILD_DIE"            => \$pre_build_die,
+    "POST_BUILD_DIE"           => \$post_build_die,
+    "POWER_CYCLE"              => \$power_cycle,
+    "REBOOT"                   => \$reboot,
+    "BUILD_NOCLEAN"            => \$noclean,
+    "MIN_CONFIG"               => \$minconfig,
+    "OUTPUT_MIN_CONFIG"                => \$output_minconfig,
+    "START_MIN_CONFIG"         => \$start_minconfig,
+    "IGNORE_CONFIG"            => \$ignore_config,
+    "TEST"                     => \$run_test,
+    "ADD_CONFIG"               => \$addconfig,
+    "REBOOT_TYPE"              => \$reboot_type,
+    "GRUB_MENU"                        => \$grub_menu,
+    "POST_INSTALL"             => \$post_install,
+    "NO_INSTALL"               => \$no_install,
+    "REBOOT_SCRIPT"            => \$reboot_script,
+    "REBOOT_ON_ERROR"          => \$reboot_on_error,
+    "SWITCH_TO_GOOD"           => \$switch_to_good,
+    "SWITCH_TO_TEST"           => \$switch_to_test,
+    "POWEROFF_ON_ERROR"                => \$poweroff_on_error,
+    "DIE_ON_FAILURE"           => \$die_on_failure,
+    "POWER_OFF"                        => \$power_off,
+    "POWERCYCLE_AFTER_REBOOT"  => \$powercycle_after_reboot,
+    "POWEROFF_AFTER_HALT"      => \$poweroff_after_halt,
+    "SLEEP_TIME"               => \$sleep_time,
+    "BISECT_SLEEP_TIME"                => \$bisect_sleep_time,
+    "PATCHCHECK_SLEEP_TIME"    => \$patchcheck_sleep_time,
+    "IGNORE_WARNINGS"          => \$ignore_warnings,
+    "IGNORE_ERRORS"            => \$ignore_errors,
+    "BISECT_MANUAL"            => \$bisect_manual,
+    "BISECT_SKIP"              => \$bisect_skip,
+    "CONFIG_BISECT_GOOD"       => \$config_bisect_good,
+    "BISECT_RET_GOOD"          => \$bisect_ret_good,
+    "BISECT_RET_BAD"           => \$bisect_ret_bad,
+    "BISECT_RET_SKIP"          => \$bisect_ret_skip,
+    "BISECT_RET_ABORT"         => \$bisect_ret_abort,
+    "BISECT_RET_DEFAULT"       => \$bisect_ret_default,
+    "STORE_FAILURES"           => \$store_failures,
+    "STORE_SUCCESSES"          => \$store_successes,
+    "TEST_NAME"                        => \$test_name,
+    "TIMEOUT"                  => \$timeout,
+    "BOOTED_TIMEOUT"           => \$booted_timeout,
+    "CONSOLE"                  => \$console,
+    "DETECT_TRIPLE_FAULT"      => \$detect_triplefault,
+    "SUCCESS_LINE"             => \$success_line,
+    "REBOOT_SUCCESS_LINE"      => \$reboot_success_line,
+    "STOP_AFTER_SUCCESS"       => \$stop_after_success,
+    "STOP_AFTER_FAILURE"       => \$stop_after_failure,
+    "STOP_TEST_AFTER"          => \$stop_test_after,
+    "BUILD_TARGET"             => \$build_target,
+    "SSH_EXEC"                 => \$ssh_exec,
+    "SCP_TO_TARGET"            => \$scp_to_target,
+    "CHECKOUT"                 => \$checkout,
+    "TARGET_IMAGE"             => \$target_image,
+    "LOCALVERSION"             => \$localversion,
+
+    "BISECT_GOOD"              => \$bisect_good,
+    "BISECT_BAD"               => \$bisect_bad,
+    "BISECT_TYPE"              => \$bisect_type,
+    "BISECT_START"             => \$bisect_start,
+    "BISECT_REPLAY"            => \$bisect_replay,
+    "BISECT_FILES"             => \$bisect_files,
+    "BISECT_REVERSE"           => \$bisect_reverse,
+    "BISECT_CHECK"             => \$bisect_check,
+
+    "CONFIG_BISECT"            => \$config_bisect,
+    "CONFIG_BISECT_TYPE"       => \$config_bisect_type,
+
+    "PATCHCHECK_TYPE"          => \$patchcheck_type,
+    "PATCHCHECK_START"         => \$patchcheck_start,
+    "PATCHCHECK_END"           => \$patchcheck_end,
+);
+
+# Options may be used by other options, record them.
+my %used_options;
+
 # default variables that can be used
 chomp ($variable{"PWD"} = `pwd`);
 
 $config_help{"MACHINE"} = << "EOF"
  The machine hostname that you will test.
+ For build only tests, it is still needed to differentiate log files.
 EOF
     ;
 $config_help{"SSH_USER"} = << "EOF"
@@ -150,11 +282,15 @@ EOF
     ;
 $config_help{"BUILD_DIR"} = << "EOF"
  The directory that contains the Linux source code (full path).
+ You can use \${PWD} that will be the path where ktest.pl is run, or use
+ \${THIS_DIR} which is assigned \${PWD} but may be changed later.
 EOF
     ;
 $config_help{"OUTPUT_DIR"} = << "EOF"
  The directory that the objects will be built (full path).
  (can not be same as BUILD_DIR)
+ You can use \${PWD} that will be the path where ktest.pl is run, or use
+ \${THIS_DIR} which is assigned \${PWD} but may be changed later.
 EOF
     ;
 $config_help{"BUILD_TARGET"} = << "EOF"
@@ -162,6 +298,11 @@ $config_help{"BUILD_TARGET"} = << "EOF"
  (relative to OUTPUT_DIR)
 EOF
     ;
+$config_help{"BUILD_OPTIONS"} = << "EOF"
+ Options to add to \"make\" when building.
+ i.e.  -j20
+EOF
+    ;
 $config_help{"TARGET_IMAGE"} = << "EOF"
  The place to put your image on the test machine.
 EOF
@@ -227,20 +368,36 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
 EOF
     ;
 
-sub read_yn {
-    my ($prompt) = @_;
+sub read_prompt {
+    my ($cancel, $prompt) = @_;
 
     my $ans;
 
     for (;;) {
-       print "$prompt [Y/n] ";
+       if ($cancel) {
+           print "$prompt [y/n/C] ";
+       } else {
+           print "$prompt [Y/n] ";
+       }
        $ans = <STDIN>;
        chomp $ans;
        if ($ans =~ /^\s*$/) {
-           $ans = "y";
+           if ($cancel) {
+               $ans = "c";
+           } else {
+               $ans = "y";
+           }
        }
        last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
-       print "Please answer either 'y' or 'n'.\n";
+       if ($cancel) {
+           last if ($ans =~ /^c$/i);
+           print "Please answer either 'y', 'n' or 'c'.\n";
+       } else {
+           print "Please answer either 'y' or 'n'.\n";
+       }
+    }
+    if ($ans =~ /^c/i) {
+       exit;
     }
     if ($ans !~ /^y$/i) {
        return 0;
@@ -248,6 +405,18 @@ sub read_yn {
     return 1;
 }
 
+sub read_yn {
+    my ($prompt) = @_;
+
+    return read_prompt 0, $prompt;
+}
+
+sub read_ync {
+    my ($prompt) = @_;
+
+    return read_prompt 1, $prompt;
+}
+
 sub get_ktest_config {
     my ($config) = @_;
     my $ans;
@@ -261,7 +430,7 @@ sub get_ktest_config {
 
     for (;;) {
        print "$config = ";
-       if (defined($default{$config})) {
+       if (defined($default{$config}) && length($default{$config})) {
            print "\[$default{$config}\] ";
        }
        $ans = <STDIN>;
@@ -274,22 +443,37 @@ sub get_ktest_config {
                next;
            }
        }
-       $entered_configs{$config} = process_variables($ans);
+       $entered_configs{$config} = ${ans};
        last;
     }
 }
 
 sub get_ktest_configs {
     get_ktest_config("MACHINE");
-    get_ktest_config("SSH_USER");
     get_ktest_config("BUILD_DIR");
     get_ktest_config("OUTPUT_DIR");
-    get_ktest_config("BUILD_TARGET");
-    get_ktest_config("TARGET_IMAGE");
-    get_ktest_config("POWER_CYCLE");
-    get_ktest_config("CONSOLE");
+
+    if ($newconfig) {
+       get_ktest_config("BUILD_OPTIONS");
+    }
+
+    # options required for other than just building a kernel
+    if (!$buildonly) {
+       get_ktest_config("POWER_CYCLE");
+       get_ktest_config("CONSOLE");
+    }
+
+    # options required for install and more
+    if ($buildonly != 1) {
+       get_ktest_config("SSH_USER");
+       get_ktest_config("BUILD_TARGET");
+       get_ktest_config("TARGET_IMAGE");
+    }
+
     get_ktest_config("LOCALVERSION");
 
+    return if ($buildonly);
+
     my $rtype = $opt{"REBOOT_TYPE"};
 
     if (!defined($rtype)) {
@@ -303,8 +487,6 @@ sub get_ktest_configs {
 
     if ($rtype eq "grub") {
        get_ktest_config("GRUB_MENU");
-    } else {
-       get_ktest_config("REBOOT_SCRIPT");
     }
 }
 
@@ -334,6 +516,10 @@ sub process_variables {
        } else {
            # put back the origin piece.
            $retval = "$retval\$\{$var\}";
+           # This could be an option that is used later, save
+           # it so we don't warn if this option is not one of
+           # ktests options.
+           $used_options{$var} = 1;
        }
        $value = $end;
     }
@@ -348,6 +534,19 @@ sub process_variables {
 sub set_value {
     my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
 
+    my $prvalue = process_variables($rvalue);
+
+    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
+       # Note if a test is something other than build, then we
+       # will need other manditory options.
+       if ($prvalue ne "install") {
+           $buildonly = 0;
+       } else {
+           # install still limits some manditory options.
+           $buildonly = 2;
+       }
+    }
+
     if (defined($opt{$lvalue})) {
        if (!$override || defined(${$overrides}{$lvalue})) {
            my $extra = "";
@@ -356,13 +555,12 @@ sub set_value {
            }
            die "$name: $.: Option $lvalue defined more than once!\n$extra";
        }
-       ${$overrides}{$lvalue} = $rvalue;
+       ${$overrides}{$lvalue} = $prvalue;
     }
     if ($rvalue =~ /^\s*$/) {
        delete $opt{$lvalue};
     } else {
-       $rvalue = process_variables($rvalue);
-       $opt{$lvalue} = $rvalue;
+       $opt{$lvalue} = $prvalue;
     }
 }
 
@@ -712,6 +910,15 @@ sub __read_config {
     return $test_case;
 }
 
+sub get_test_case {
+       print "What test case would you like to run?\n";
+       print " (build, install or boot)\n";
+       print " Other tests are available but require editing the config file\n";
+       my $ans = <STDIN>;
+       chomp $ans;
+       $default{"TEST_TYPE"} = $ans;
+}
+
 sub read_config {
     my ($config) = @_;
 
@@ -726,10 +933,7 @@ sub read_config {
     # was a test specified?
     if (!$test_case) {
        print "No test case specified.\n";
-       print "What test case would you like to run?\n";
-       my $ans = <STDIN>;
-       chomp $ans;
-       $default{"TEST_TYPE"} = $ans;
+       get_test_case;
     }
 
     # set any defaults
@@ -739,6 +943,37 @@ sub read_config {
            $opt{$default} = $default{$default};
        }
     }
+
+    if ($opt{"IGNORE_UNUSED"} == 1) {
+       return;
+    }
+
+    my %not_used;
+
+    # check if there are any stragglers (typos?)
+    foreach my $option (keys %opt) {
+       my $op = $option;
+       # remove per test labels.
+       $op =~ s/\[.*\]//;
+       if (!exists($option_map{$op}) &&
+           !exists($default{$op}) &&
+           !exists($used_options{$op})) {
+           $not_used{$op} = 1;
+       }
+    }
+
+    if (%not_used) {
+       my $s = "s are";
+       $s = " is" if (keys %not_used == 1);
+       print "The following option$s not used; could be a typo:\n";
+       foreach my $option (keys %not_used) {
+           print "$option\n";
+       }
+       print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
+       if (!read_yn "Do you want to continue?") {
+           exit -1;
+       }
+    }
 }
 
 sub __eval_option {
@@ -873,6 +1108,17 @@ sub reboot {
     }
 }
 
+sub reboot_to_good {
+    my ($time) = @_;
+
+    if (defined($switch_to_good)) {
+       run_command $switch_to_good;
+       return;
+    }
+
+    reboot $time;
+}
+
 sub do_not_reboot {
     my $i = $iteration;
 
@@ -889,7 +1135,7 @@ sub dodie {
     if ($reboot_on_error && !do_not_reboot) {
 
        doprint "REBOOTING\n";
-       reboot;
+       reboot_to_good;
 
     } elsif ($poweroff_on_error && defined($power_off)) {
        doprint "POWERING OFF\n";
@@ -975,6 +1221,43 @@ sub wait_for_monitor {
     print "** Monitor flushed **\n";
 }
 
+sub save_logs {
+       my ($result, $basedir) = @_;
+       my @t = localtime;
+       my $date = sprintf "%04d%02d%02d%02d%02d%02d",
+               1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
+
+       my $type = $build_type;
+       if ($type =~ /useconfig/) {
+           $type = "useconfig";
+       }
+
+       my $dir = "$machine-$test_type-$type-$result-$date";
+
+       $dir = "$basedir/$dir";
+
+       if (!-d $dir) {
+           mkpath($dir) or
+               die "can't create $dir";
+       }
+
+       my %files = (
+               "config" => $output_config,
+               "buildlog" => $buildlog,
+               "dmesg" => $dmesg,
+               "testlog" => $testlog,
+       );
+
+       while (my ($name, $source) = each(%files)) {
+               if (-f "$source") {
+                       cp "$source", "$dir/$name" or
+                               die "failed to copy $source";
+               }
+       }
+
+       doprint "*** Saved info to $dir ***\n";
+}
+
 sub fail {
 
        if ($die_on_failure) {
@@ -988,7 +1271,7 @@ sub fail {
        # no need to reboot for just building.
        if (!do_not_reboot) {
            doprint "REBOOTING\n";
-           reboot $sleep_time;
+           reboot_to_good $sleep_time;
        }
 
        my $name = "";
@@ -1003,38 +1286,9 @@ sub fail {
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
        doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 
-       return 1 if (!defined($store_failures));
-
-       my @t = localtime;
-       my $date = sprintf "%04d%02d%02d%02d%02d%02d",
-               1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
-
-       my $type = $build_type;
-       if ($type =~ /useconfig/) {
-           $type = "useconfig";
-       }
-
-       my $dir = "$machine-$test_type-$type-fail-$date";
-       my $faildir = "$store_failures/$dir";
-
-       if (!-d $faildir) {
-           mkpath($faildir) or
-               die "can't create $faildir";
-       }
-       if (-f "$output_config") {
-           cp "$output_config", "$faildir/config" or
-               die "failed to copy .config";
-       }
-       if (-f $buildlog) {
-           cp $buildlog, "$faildir/buildlog" or
-               die "failed to move $buildlog";
-       }
-       if (-f $dmesg) {
-           cp $dmesg, "$faildir/dmesg" or
-               die "failed to move $dmesg";
-       }
-
-       doprint "*** Saved info to $faildir ***\n";
+       if (defined($store_failures)) {
+           save_logs "fail", $store_failures;
+        }
 
        return 1;
 }
@@ -1170,13 +1424,16 @@ sub wait_for_input
 }
 
 sub reboot_to {
+    if (defined($switch_to_test)) {
+       run_command $switch_to_test;
+    }
+
     if ($reboot_type eq "grub") {
        run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
-       reboot;
-       return;
+    } elsif (defined $reboot_script) {
+       run_command "$reboot_script";
     }
-
-    run_command "$reboot_script";
+    reboot;
 }
 
 sub get_sha1 {
@@ -1274,7 +1531,7 @@ sub monitor {
        }
 
        if ($full_line =~ /call trace:/i) {
-           if (!$bug && !$skip_call_trace) {
+           if (!$ignore_errors && !$bug && !$skip_call_trace) {
                $bug = 1;
                $failure_start = time;
            }
@@ -1341,12 +1598,19 @@ sub monitor {
     return 1;
 }
 
+sub eval_kernel_version {
+    my ($option) = @_;
+
+    $option =~ s/\$KERNEL_VERSION/$version/g;
+
+    return $option;
+}
+
 sub do_post_install {
 
     return if (!defined($post_install));
 
-    my $cp_post_install = $post_install;
-    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
+    my $cp_post_install = eval_kernel_version $post_install;
     run_command "$cp_post_install" or
        dodie "Failed to run post install";
 }
@@ -1355,7 +1619,9 @@ sub install {
 
     return if ($no_install);
 
-    run_scp "$outputdir/$build_target", "$target_image" or
+    my $cp_target = eval_kernel_version $target_image;
+
+    run_scp "$outputdir/$build_target", "$cp_target" or
        dodie "failed to copy image";
 
     my $install_mods = 0;
@@ -1640,9 +1906,13 @@ sub success {
     doprint     "*******************************************\n";
     doprint     "*******************************************\n";
 
+    if (defined($store_successes)) {
+        save_logs "success", $store_successes;
+    }
+
     if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot $sleep_time;
+       reboot_to_good $sleep_time;
     }
 }
 
@@ -1669,7 +1939,10 @@ sub child_run_test {
     $poweroff_on_error = 0;
     $die_on_failure = 1;
 
+    $redirect = "$testlog";
     run_command $run_test or $failed = 1;
+    undef $redirect;
+
     exit $failed;
 }
 
@@ -1744,6 +2017,43 @@ sub do_run_test {
     waitpid $child_pid, 0;
     $child_exit = $?;
 
+    if (!$bug && $in_bisect) {
+       if (defined($bisect_ret_good)) {
+           if ($child_exit == $bisect_ret_good) {
+               return 1;
+           }
+       }
+       if (defined($bisect_ret_skip)) {
+           if ($child_exit == $bisect_ret_skip) {
+               return -1;
+           }
+       }
+       if (defined($bisect_ret_abort)) {
+           if ($child_exit == $bisect_ret_abort) {
+               fail "test abort" and return -2;
+           }
+       }
+       if (defined($bisect_ret_bad)) {
+           if ($child_exit == $bisect_ret_skip) {
+               return 0;
+           }
+       }
+       if (defined($bisect_ret_default)) {
+           if ($bisect_ret_default eq "good") {
+               return 1;
+           } elsif ($bisect_ret_default eq "bad") {
+               return 0;
+           } elsif ($bisect_ret_default eq "skip") {
+               return -1;
+           } elsif ($bisect_ret_default eq "abort") {
+               return -2;
+           } else {
+               fail "unknown default action: $bisect_ret_default"
+                   and return -2;
+           }
+       }
+    }
+
     if ($bug || $child_exit) {
        return 0 if $in_bisect;
        fail "test failed" and return 0;
@@ -1770,7 +2080,7 @@ sub run_git_bisect {
     if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
        doprint "$1 [$2]\n";
     } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
-       $bisect_bad = $1;
+       $bisect_bad_commit = $1;
        doprint "Found bad commit... $1\n";
        return 0;
     } else {
@@ -1783,7 +2093,7 @@ sub run_git_bisect {
 
 sub bisect_reboot {
     doprint "Reboot and sleep $bisect_sleep_time seconds\n";
-    reboot $bisect_sleep_time;
+    reboot_to_good $bisect_sleep_time;
 }
 
 # returns 1 on success, 0 on failure, -1 on skip
@@ -1868,21 +2178,28 @@ sub run_bisect {
     }
 }
 
+sub update_bisect_replay {
+    my $tmp_log = "$tmpdir/ktest_bisect_log";
+    run_command "git bisect log > $tmp_log" or
+       die "can't create bisect log";
+    return $tmp_log;
+}
+
 sub bisect {
     my ($i) = @_;
 
     my $result;
 
-    die "BISECT_GOOD[$i] not defined\n"        if (!defined($opt{"BISECT_GOOD[$i]"}));
-    die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
-    die "BISECT_TYPE[$i] not defined\n"        if (!defined($opt{"BISECT_TYPE[$i]"}));
+    die "BISECT_GOOD[$i] not defined\n"        if (!defined($bisect_good));
+    die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
+    die "BISECT_TYPE[$i] not defined\n"        if (!defined($bisect_type));
 
-    my $good = $opt{"BISECT_GOOD[$i]"};
-    my $bad = $opt{"BISECT_BAD[$i]"};
-    my $type = $opt{"BISECT_TYPE[$i]"};
-    my $start = $opt{"BISECT_START[$i]"};
-    my $replay = $opt{"BISECT_REPLAY[$i]"};
-    my $start_files = $opt{"BISECT_FILES[$i]"};
+    my $good = $bisect_good;
+    my $bad = $bisect_bad;
+    my $type = $bisect_type;
+    my $start = $bisect_start;
+    my $replay = $bisect_replay;
+    my $start_files = $bisect_files;
 
     if (defined($start_files)) {
        $start_files = " -- " . $start_files;
@@ -1894,8 +2211,7 @@ sub bisect {
     $good = get_sha1($good);
     $bad = get_sha1($bad);
 
-    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
-       $opt{"BISECT_REVERSE[$i]"} == 1) {
+    if (defined($bisect_reverse) && $bisect_reverse == 1) {
        doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
        $reverse_bisect = 1;
     } else {
@@ -1907,8 +2223,31 @@ sub bisect {
        $type = "boot";
     }
 
-    my $check = $opt{"BISECT_CHECK[$i]"};
-    if (defined($check) && $check ne "0") {
+    # Check if a bisect was running
+    my $bisect_start_file = "$builddir/.git/BISECT_START";
+
+    my $check = $bisect_check;
+    my $do_check = defined($check) && $check ne "0";
+
+    if ( -f $bisect_start_file ) {
+       print "Bisect in progress found\n";
+       if ($do_check) {
+           print " If you say yes, then no checks of good or bad will be done\n";
+       }
+       if (defined($replay)) {
+           print "** BISECT_REPLAY is defined in config file **";
+           print " Ignore config option and perform new git bisect log?\n";
+           if (read_ync " (yes, no, or cancel) ") {
+               $replay = update_bisect_replay;
+               $do_check = 0;
+           }
+       } elsif (read_yn "read git log and continue?") {
+           $replay = update_bisect_replay;
+           $do_check = 0;
+       }
+    }
+
+    if ($do_check) {
 
        # get current HEAD
        my $head = get_sha1("HEAD");
@@ -1973,7 +2312,7 @@ sub bisect {
     run_command "git bisect reset" or
        dodie "could not reset git bisect";
 
-    doprint "Bad commit was [$bisect_bad]\n";
+    doprint "Bad commit was [$bisect_bad_commit]\n";
 
     success $i;
 }
@@ -2129,7 +2468,7 @@ sub run_config_bisect {
     }
 
     doprint "***** RUN TEST ***\n";
-    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
+    my $type = $config_bisect_type;
     my $ret;
     my %current_config;
 
@@ -2233,7 +2572,7 @@ sub run_config_bisect {
 sub config_bisect {
     my ($i) = @_;
 
-    my $start_config = $opt{"CONFIG_BISECT[$i]"};
+    my $start_config = $config_bisect;
 
     my $tmpconfig = "$tmpdir/use_config";
 
@@ -2346,29 +2685,29 @@ sub config_bisect {
 
 sub patchcheck_reboot {
     doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
-    reboot $patchcheck_sleep_time;
+    reboot_to_good $patchcheck_sleep_time;
 }
 
 sub patchcheck {
     my ($i) = @_;
 
     die "PATCHCHECK_START[$i] not defined\n"
-       if (!defined($opt{"PATCHCHECK_START[$i]"}));
+       if (!defined($patchcheck_start));
     die "PATCHCHECK_TYPE[$i] not defined\n"
-       if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
+       if (!defined($patchcheck_type));
 
-    my $start = $opt{"PATCHCHECK_START[$i]"};
+    my $start = $patchcheck_start;
 
     my $end = "HEAD";
-    if (defined($opt{"PATCHCHECK_END[$i]"})) {
-       $end = $opt{"PATCHCHECK_END[$i]"};
+    if (defined($patchcheck_end)) {
+       $end = $patchcheck_end;
     }
 
     # Get the true sha1's since we can use things like HEAD~3
     $start = get_sha1($start);
     $end = get_sha1($end);
 
-    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
+    my $type = $patchcheck_type;
 
     # Can't have a test without having a test to run
     if ($type eq "test" && !defined($run_test)) {
@@ -2963,7 +3302,7 @@ sub make_min_config {
        }
 
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot $sleep_time;
+       reboot_to_good $sleep_time;
     }
 
     success $i;
@@ -2985,13 +3324,27 @@ if ($#ARGV == 0) {
 }
 
 if (! -f $ktest_config) {
+    $newconfig = 1;
+    get_test_case;
     open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
     print OUT << "EOF"
 # Generated by ktest.pl
 #
+
+# PWD is a ktest.pl variable that will result in the process working
+# directory that ktest.pl is executed in.
+
+# THIS_DIR is automatically assigned the PWD of the path that generated
+# the config file. It is best to use this variable when assigning other
+# directory paths within this directory. This allows you to easily
+# move the test cases to other locations or to other machines.
+#
+THIS_DIR := $variable{"PWD"}
+
 # Define each test with TEST_START
 # The config options below it will override the defaults
 TEST_START
+TEST_TYPE = $default{"TEST_TYPE"}
 
 DEFAULTS
 EOF
@@ -3011,7 +3364,7 @@ if ($#new_configs >= 0) {
     open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
     foreach my $config (@new_configs) {
        print OUT "$config = $entered_configs{$config}\n";
-       $opt{$config} = $entered_configs{$config};
+       $opt{$config} = process_variables($entered_configs{$config});
     }
 }
 
@@ -3091,61 +3444,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     my $makecmd = set_test_option("MAKE_CMD", $i);
 
-    $machine = set_test_option("MACHINE", $i);
-    $ssh_user = set_test_option("SSH_USER", $i);
-    $tmpdir = set_test_option("TMP_DIR", $i);
-    $outputdir = set_test_option("OUTPUT_DIR", $i);
-    $builddir = set_test_option("BUILD_DIR", $i);
-    $test_type = set_test_option("TEST_TYPE", $i);
-    $build_type = set_test_option("BUILD_TYPE", $i);
-    $build_options = set_test_option("BUILD_OPTIONS", $i);
-    $pre_build = set_test_option("PRE_BUILD", $i);
-    $post_build = set_test_option("POST_BUILD", $i);
-    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
-    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
-    $power_cycle = set_test_option("POWER_CYCLE", $i);
-    $reboot = set_test_option("REBOOT", $i);
-    $noclean = set_test_option("BUILD_NOCLEAN", $i);
-    $minconfig = set_test_option("MIN_CONFIG", $i);
-    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
-    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
-    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
-    $run_test = set_test_option("TEST", $i);
-    $addconfig = set_test_option("ADD_CONFIG", $i);
-    $reboot_type = set_test_option("REBOOT_TYPE", $i);
-    $grub_menu = set_test_option("GRUB_MENU", $i);
-    $post_install = set_test_option("POST_INSTALL", $i);
-    $no_install = set_test_option("NO_INSTALL", $i);
-    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
-    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
-    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
-    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
-    $power_off = set_test_option("POWER_OFF", $i);
-    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
-    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
-    $sleep_time = set_test_option("SLEEP_TIME", $i);
-    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
-    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
-    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
-    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
-    $bisect_skip = set_test_option("BISECT_SKIP", $i);
-    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
-    $store_failures = set_test_option("STORE_FAILURES", $i);
-    $test_name = set_test_option("TEST_NAME", $i);
-    $timeout = set_test_option("TIMEOUT", $i);
-    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
-    $console = set_test_option("CONSOLE", $i);
-    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
-    $success_line = set_test_option("SUCCESS_LINE", $i);
-    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
-    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
-    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
-    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
-    $build_target = set_test_option("BUILD_TARGET", $i);
-    $ssh_exec = set_test_option("SSH_EXEC", $i);
-    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
-    $target_image = set_test_option("TARGET_IMAGE", $i);
-    $localversion = set_test_option("LOCALVERSION", $i);
+    # Load all the options into their mapped variable names
+    foreach my $opt (keys %option_map) {
+       ${$option_map{$opt}} = set_test_option($opt, $i);
+    }
 
     $start_minconfig_defined = 1;
 
@@ -3166,26 +3468,26 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $ENV{"SSH_USER"} = $ssh_user;
     $ENV{"MACHINE"} = $machine;
 
-    $target = "$ssh_user\@$machine";
-
     $buildlog = "$tmpdir/buildlog-$machine";
+    $testlog = "$tmpdir/testlog-$machine";
     $dmesg = "$tmpdir/dmesg-$machine";
     $make = "$makecmd O=$outputdir";
     $output_config = "$outputdir/.config";
 
-    if ($reboot_type eq "grub") {
-       dodie "GRUB_MENU not defined" if (!defined($grub_menu));
-    } elsif (!defined($reboot_script)) {
-       dodie "REBOOT_SCRIPT not defined"
+    if (!$buildonly) {
+       $target = "$ssh_user\@$machine";
+       if ($reboot_type eq "grub") {
+           dodie "GRUB_MENU not defined" if (!defined($grub_menu));
+       }
     }
 
     my $run_type = $build_type;
     if ($test_type eq "patchcheck") {
-       $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
+       $run_type = $patchcheck_type;
     } elsif ($test_type eq "bisect") {
-       $run_type = $opt{"BISECT_TYPE[$i]"};
+       $run_type = $bisect_type;
     } elsif ($test_type eq "config_bisect") {
-       $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
+       $run_type = $config_bisect_type;
     }
 
     if ($test_type eq "make_min_config") {
@@ -3205,6 +3507,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     unlink $dmesg;
     unlink $buildlog;
+    unlink $testlog;
 
     if (defined($addconfig)) {
        my $min = $minconfig;
@@ -3216,7 +3519,6 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $minconfig = "$tmpdir/add_config";
     }
 
-    my $checkout = $opt{"CHECKOUT[$i]"};
     if (defined($checkout)) {
        run_command "git checkout $checkout" or
            die "failed to checkout $checkout";
@@ -3267,7 +3569,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 if ($opt{"POWEROFF_ON_SUCCESS"}) {
     halt;
 } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
-    reboot;
+    reboot_to_good;
 }
 
 doprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
index 553c06b7d6f27ad8e72f8e8e943321271099a237..5ea04c6a71bfc830feca1c10c144264ba97a5db3 100644 (file)
 #GRUB_MENU = Test Kernel
 
 # A script to reboot the target into the test kernel
-# (Only mandatory if REBOOT_TYPE = script)
+# This and SWITCH_TO_TEST are about the same, except
+# SWITCH_TO_TEST is run even for REBOOT_TYPE = grub.
+# This may be left undefined.
+# (default undefined)
 #REBOOT_SCRIPT =
 
 #### Optional Config Options (all have defaults) ####
 # The test will not modify that file.
 #REBOOT_TYPE = grub
 
+# If you are using a machine that doesn't boot with grub, and
+# perhaps gets its kernel from a remote server (tftp), then
+# you can use this option to update the target image with the
+# test image.
+#
+# You could also do the same with POST_INSTALL, but the difference
+# between that option and this option is that POST_INSTALL runs
+# after the install, where this one runs just before a reboot.
+# (default undefined)
+#SWITCH_TO_TEST = cp ${OUTPUT_DIR}/${BUILD_TARGET} ${TARGET_IMAGE}
+
+# If you are using a machine that doesn't boot with grub, and
+# perhaps gets its kernel from a remote server (tftp), then
+# you can use this option to update the target image with the
+# the known good image to reboot safely back into.
+#
+# This option holds a command that will execute before needing
+# to reboot to a good known image.
+# (default undefined)
+#SWITCH_TO_GOOD = ssh ${SSH_USER}/${MACHINE} cp good_image ${TARGET_IMAGE}
+
 # The min config that is needed to build for the machine
 # A nice way to create this is with the following:
 #
 # (default undefined)
 #STORE_FAILURES = /home/test/failures
 
+# Directory to store success directories on success. If this is not
+# set, the .config, dmesg and bootlog will not be saved if a
+# test succeeds.
+# (default undefined)
+#STORE_SUCCESSES = /home/test/successes
+
 # Build without doing a make mrproper, or removing .config
 # (default 0)
 #BUILD_NOCLEAN = 0
 # (default 1)
 #DETECT_TRIPLE_FAULT = 0
 
+# All options in the config file should be either used by ktest
+# or could be used within a value of another option. If an option
+# in the config file is not used, ktest will warn about it and ask
+# if you want to continue.
+#
+# If you don't care if there are non-used options, enable this
+# option. Be careful though, a non-used option is usually a sign
+# of an option name being typed incorrectly.
+# (default 0)
+#IGNORE_UNUSED = 1
+
+# When testing a kernel that happens to have WARNINGs, and call
+# traces, ktest.pl will detect these and fail a boot or test run
+# due to warnings. By setting this option, ktest will ignore
+# call traces, and will not fail a test if the kernel produces
+# an oops. Use this option with care.
+# (default 0)
+#IGNORE_ERRORS = 1
+
 #### Per test run options ####
 # The following options are only allowed in TEST_START sections.
 # They are ignored in the DEFAULTS sections.
 #   BISECT_BAD with BISECT_CHECK = good or
 #   BISECT_CHECK = bad, respectively.
 #
+# BISECT_RET_GOOD = 0 (optional, default undefined)
+#
+#   In case the specificed test returns something other than just
+#   0 for good, and non-zero for bad, you can override 0 being
+#   good by defining BISECT_RET_GOOD.
+#
+# BISECT_RET_BAD = 1 (optional, default undefined)
+#
+#   In case the specificed test returns something other than just
+#   0 for good, and non-zero for bad, you can override non-zero being
+#   bad by defining BISECT_RET_BAD.
+#
+# BISECT_RET_ABORT = 255 (optional, default undefined)
+#
+#   If you need to abort the bisect if the test discovers something
+#   that was wrong, you can define BISECT_RET_ABORT to be the error
+#   code returned by the test in order to abort the bisect.
+#
+# BISECT_RET_SKIP = 2 (optional, default undefined)
+#
+#   If the test detects that the current commit is neither good
+#   nor bad, but something else happened (another bug detected)
+#   you can specify BISECT_RET_SKIP to an error code that the
+#   test returns when it should skip the current commit.
+#
+# BISECT_RET_DEFAULT = good (optional, default undefined)
+#
+#   You can override the default of what to do when the above
+#   options are not hit. This may be one of, "good", "bad",
+#   "abort" or "skip" (without the quotes).
+#
+#   Note, if you do not define any of the previous BISECT_RET_*
+#   and define BISECT_RET_DEFAULT, all bisects results will do
+#   what the BISECT_RET_DEFAULT has.
+#
+#
 # Example:
 #   TEST_START
 #   TEST_TYPE = bisect
This page took 1.247057 seconds and 5 git commands to generate.