]> err.no Git - linux-2.6/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Apr 2008 18:21:08 +0000 (11:21 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Apr 2008 18:21:08 +0000 (11:21 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (452 commits)
  V4L/DVB (7731): tuner-xc2028: fix signal strength calculus
  V4L/DVB (7730): tuner-xc2028: Fix SCODE load for MTS firmwares
  V4L/DVB (7729): Fix VIDIOCGAP corruption in ivtv
  V4L/DVB (7728): tea5761: bugzilla #10462: tea5761 autodetection code were broken
  V4L/DVB (7726): cx23885: Enable cx23417 support on the HVR1800
  V4L/DVB (7725): cx23885: Add generic cx23417 hardware encoder support
  V4L/DVB (7723): pvrusb2: Clean up input selection list generation in V4L interface
  V4L/DVB (7722): pvrusb2: Implement FM radio support for Gotview USB2.0 DVD 2
  V4L/DVB (7721): pvrusb2: Restructure cx23416 firmware loading to have a common exit point
  V4L/DVB (7720): pvrusb2: Fix bad error code on cx23416 firmware load failure
  V4L/DVB (7719): pvrusb2: Implement input selection enforcement
  V4L/DVB (7718): pvrusb2-dvb: update Kbuild selections
  V4L/DVB (7717): pvrusb2-dvb: add DVB-T support for Hauppauge pvrusb2 model 73xxx
  V4L/DVB (7716): pvrusb2: clean up global functions
  V4L/DVB (7715): pvrusb2: Clean out all use of __FUNCTION__
  V4L/DVB (7714): pvrusb2: Fix hang on module removal
  V4L/DVB (7713): pvrusb2: Implement cleaner DVB kernel thread shutdown
  V4L/DVB (7712): pvrusb2: Close connect/disconnect race
  V4L/DVB (7711): pvrusb2: Fix race on module unload
  V4L/DVB (7710): pvrusb2: Implement critical digital streaming quirk for onair devices
  ...

428 files changed:
Documentation/video4linux/CARDLIST.au0828 [new file with mode: 0644]
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/extract_xc3028.pl
drivers/media/Kconfig
drivers/media/common/ir-functions.c
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_i2c.c
drivers/media/common/saa7146_vbi.c
drivers/media/common/saa7146_video.c
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/Makefile
drivers/media/dvb/b2c2/flexcop-common.h
drivers/media/dvb/b2c2/flexcop-dma.c
drivers/media/dvb/b2c2/flexcop-eeprom.c
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/dvb/b2c2/flexcop-misc.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/b2c2/flexcop-reg.h
drivers/media/dvb/b2c2/flexcop-sram.c
drivers/media/dvb/b2c2/flexcop-usb.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/Makefile
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/af9005.c
drivers/media/dvb/dvb-usb/au6610.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-common.h
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-init.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/gl861.c
drivers/media/dvb/dvb-usb/gp8psk-fe.c
drivers/media/dvb/dvb-usb/gp8psk.c
drivers/media/dvb/dvb-usb/m920x.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/opera1.c
drivers/media/dvb/dvb-usb/ttusb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/vp702x-fe.c
drivers/media/dvb/dvb-usb/vp702x.c
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/au8522.c [new file with mode: 0644]
drivers/media/dvb/frontends/au8522.h [new file with mode: 0644]
drivers/media/dvb/frontends/bcm3510.c
drivers/media/dvb/frontends/bcm3510.h
drivers/media/dvb/frontends/bsbe1.h
drivers/media/dvb/frontends/bsru6.h
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22700.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24113.h [new file with mode: 0644]
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/dib3000.h
drivers/media/dvb/frontends/dib3000mc.h
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib7000p.h
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/isl6405.c [new file with mode: 0644]
drivers/media/dvb/frontends/isl6405.h [new file with mode: 0644]
drivers/media/dvb/frontends/isl6421.h
drivers/media/dvb/frontends/itd1000.c [new file with mode: 0644]
drivers/media/dvb/frontends/itd1000.h [new file with mode: 0644]
drivers/media/dvb/frontends/itd1000_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/l64781.h
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lnbp21.h
drivers/media/dvb/frontends/mt2060.h
drivers/media/dvb/frontends/mt2131.c
drivers/media/dvb/frontends/mt2131.h
drivers/media/dvb/frontends/mt2266.h
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/mt312_priv.h
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt200x.c
drivers/media/dvb/frontends/nxt200x.h
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51132.h
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/or51211.h
drivers/media/dvb/frontends/qt1010.h
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1409.h
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/s5h1420_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp8870.h
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/sp887x.h
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10023.c
drivers/media/dvb/frontends/tda1002x.h
drivers/media/dvb/frontends/tda10048.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda10048.h [new file with mode: 0644]
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda10086.c
drivers/media/dvb/frontends/tda10086.h
drivers/media/dvb/frontends/tda18271-common.c
drivers/media/dvb/frontends/tda18271-fe.c
drivers/media/dvb/frontends/tda18271-priv.h
drivers/media/dvb/frontends/tda18271-tables.c
drivers/media/dvb/frontends/tda18271.h
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda8083.h
drivers/media/dvb/frontends/tda826x.c
drivers/media/dvb/frontends/tda826x.h
drivers/media/dvb/frontends/tda827x.c
drivers/media/dvb/frontends/tda827x.h
drivers/media/dvb/frontends/tua6100.c
drivers/media/dvb/frontends/tua6100.h
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1820.h
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/frontends/ves1x93.h
drivers/media/dvb/frontends/xc5000.c
drivers/media/dvb/frontends/xc5000.h
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttpci/budget.h
drivers/media/dvb/ttpci/ttpci-eeprom.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/radio/dsbr100.c
drivers/media/radio/miropcm20-radio.c
drivers/media/radio/miropcm20-rds.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/arv.c
drivers/media/video/au0828/Kconfig [new file with mode: 0644]
drivers/media/video/au0828/Makefile [new file with mode: 0644]
drivers/media/video/au0828/au0828-cards.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-cards.h [new file with mode: 0644]
drivers/media/video/au0828/au0828-core.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-dvb.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-i2c.c [new file with mode: 0644]
drivers/media/video/au0828/au0828-reg.h [new file with mode: 0644]
drivers/media/video/au0828/au0828.h [new file with mode: 0644]
drivers/media/video/bt819.c
drivers/media/video/bt856.c
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cpia.c
drivers/media/video/cpia.h
drivers/media/video/cpia2/cpia2_core.c
drivers/media/video/cpia2/cpia2_usb.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cpia_usb.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/Makefile
drivers/media/video/cx23885/cx23885-417.c [new file with mode: 0644]
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/cx25840/cx25840-firmware.c
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-vbi.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/dabfirmware.h
drivers/media/video/dabusb.c
drivers/media/video/dpc7146.c
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/Makefile
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c [new file with mode: 0644]
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx-reg.h [new file with mode: 0644]
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/hexium_gemini.c
drivers/media/video/hexium_orion.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/Kconfig
drivers/media/video/ivtv/ivtv-cards.c
drivers/media/video/ivtv/ivtv-cards.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-mailbox.c
drivers/media/video/ivtv/ivtv-queue.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-kthreads.c
drivers/media/video/mt20xx.c
drivers/media/video/mt20xx.h
drivers/media/video/mt9m001.c [new file with mode: 0644]
drivers/media/video/mt9v022.c [new file with mode: 0644]
drivers/media/video/mxb.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/ovcamchip/ovcamchip_priv.h
drivers/media/video/pms.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/Makefile
drivers/media/video/pvrusb2/pvrusb2-context.c
drivers/media/video/pvrusb2/pvrusb2-context.h
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-debug.h
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-dvb.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-dvb.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-io.c
drivers/media/video/pvrusb2/pvrusb2-io.h
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pxa_camera.c [new file with mode: 0644]
drivers/media/video/saa5249.c
drivers/media/video/saa6588.c
drivers/media/video/saa7110.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa7115.c
drivers/media/video/saa711x.c
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-reg.h
drivers/media/video/saa7134/saa7134-ts.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134-vbi.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c [new file with mode: 0644]
drivers/media/video/saa7185.c
drivers/media/video/se401.c
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/sn9c102/sn9c102_sensor.h
drivers/media/video/soc_camera.c [new file with mode: 0644]
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tcm825x.c
drivers/media/video/tda8290.c
drivers/media/video/tda8290.h
drivers/media/video/tda9840.c
drivers/media/video/tda9887.c
drivers/media/video/tda9887.h
drivers/media/video/tea5761.c
drivers/media/video/tea5761.h
drivers/media/video/tea5767.c
drivers/media/video/tea5767.h
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-i2c.h
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-simple.h
drivers/media/video/tuner-types.c
drivers/media/video/tuner-xc2028-types.h
drivers/media/video/tuner-xc2028.c
drivers/media/video/tuner-xc2028.h
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/ibmcam.c
drivers/media/video/usbvideo/konicawc.c
drivers/media/video/usbvideo/quickcam_messenger.c
drivers/media/video/usbvideo/ultracam.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/v4l1-compat.c
drivers/media/video/videobuf-core.c
drivers/media/video/videobuf-dma-sg.c
drivers/media/video/videobuf-dvb.c
drivers/media/video/videobuf-vmalloc.c
drivers/media/video/videocodec.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/w9968cf.h
drivers/media/video/zc0301/zc0301.h
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran.h
drivers/media/video/zoran_card.c
drivers/media/video/zoran_card.h
drivers/media/video/zoran_device.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr36016.c
drivers/media/video/zr36050.c
drivers/media/video/zr36060.c
drivers/media/video/zr364xx.c
include/linux/dvb/dmx.h
include/linux/i2c-id.h
include/linux/meye.h
include/linux/videodev2.h
include/media/ir-common.h
include/media/soc_camera.h [new file with mode: 0644]
include/media/tuner-types.h
include/media/tuner.h
include/media/v4l2-chip-ident.h
include/media/v4l2-dev.h
include/media/videobuf-core.h
include/media/videobuf-dma-sg.h
include/media/videobuf-dvb.h
include/media/videobuf-vmalloc.h

diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828
new file mode 100644 (file)
index 0000000..aaae360
--- /dev/null
@@ -0,0 +1,4 @@
+  0 -> Unknown board                            (au0828)
+  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200]
+  2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
+  3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
index d97cf7cc60889e637f2772023e752fda4d44c5a3..f32efb6fb12c5111de62f875ec8361af5152e091 100644 (file)
 147 -> VoodooTV 200 (USA)                                  [121a:3000]
 148 -> DViCO FusionHDTV 2                                  [dbc0:d200]
 149 -> Typhoon TV-Tuner PCI (50684)
+150 -> Geovision GV-600                                    [008a:763c]
+151 -> Kozumi KTV-01C
index 0924e6e142c40a2f7d6a5dec0ae107ff5d616d8c..929b90c8387fafc30ed3e0715171a504e257b0e7 100644 (file)
@@ -5,3 +5,6 @@
   4 -> DViCO FusionHDTV5 Express                           [18ac:d500]
   5 -> Hauppauge WinTV-HVR1500Q                            [0070:7790,0070:7797]
   6 -> Hauppauge WinTV-HVR1500                             [0070:7710,0070:7717]
+  7 -> Hauppauge WinTV-HVR1200                             [0070:71d1]
+  8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
+  9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
index bc5593bd9704dc8497d6d69d01642938bb20f5b9..5439573464693ca9c3ac29ba9d10b0dd27a2fdf9 100644 (file)
  56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
  57 -> ADS Tech Instant Video PCI                          [1421:0390]
  58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
+ 59 -> DViCO FusionHDTV 5 PCI nano                         [18ac:d530]
+ 60 -> Pinnacle Hybrid PCTV                                [12ab:1788]
+ 61 -> Winfast TV2000 XP Global                            [107d:6f18]
+ 62 -> PowerColor Real Angel 330                           [14f1:ea3d]
+ 63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
+ 64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
+ 65 -> DViCO FusionHDTV 7 Gold                             [18ac:d610]
+ 66 -> Prolink Pixelview MPEG 8000GT                       [1554:4935]
+ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120)                 [17de:08c1]
index 0424901ebc78b0a11f700a21d926e1b4b3fe4d2f..44d84dd15ad672d55b4a93db652f34d74cb3a664 100644 (file)
@@ -25,8 +25,8 @@
  24 -> KNC One TV-Station DVR                   [1894:a006]
  25 -> ASUS TV-FM 7133                          [1043:4843]
  26 -> Pinnacle PCTV Stereo (saa7134)           [11bd:002b]
- 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
- 28 -> Manli MuchTV M-TV001/Behold TV 401
+ 27 -> Manli MuchTV M-TV002
+ 28 -> Manli MuchTV M-TV001
  29 -> Nagase Sangyo TransGear 3000TV           [1461:050c]
  30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)  [1019:4cb4]
  31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 132 -> Genius TVGO AM11MCE
+133 -> NXP Snake DVB-S reference design
+134 -> Medion/Creatix CTX953 Hybrid             [16be:0010]
+135 -> MSI TV@nywhere A/D v1.1                  [1462:8625]
+136 -> AVerMedia Cardbus TV/Radio (E506R)       [1461:f436]
+137 -> AVerMedia Hybrid TV/Radio (A16D)         [1461:f936]
+138 -> Avermedia M115                           [1461:a836]
+139 -> Compro VideoMate T750                    [185b:c900]
+140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
+141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
index cced8ac5c543b462c7cbc329c5ddac921bb05774..2cb816047fc128bb67323c00ffcd982fe5d174fc 100644 (file)
@@ -686,11 +686,11 @@ sub main_firmware($$$$)
        write_hunk(812664, 192);
 
        #
-       # Firmware 58, type: SCODE FW  HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
+       # Firmware 58, type: SCODE FW  MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192
        #
 
-       write_le32(0x60000000);                 # Type
-       write_le64(0x00000000, 0x00002000);     # ID
+       write_le32(0x6002b004);                 # Type
+       write_le64(0x00000000, 0x0000b700);     # ID
        write_le16(4500);                       # IF
        write_le32(192);                        # Size
        write_hunk(807672, 192);
@@ -706,10 +706,10 @@ sub main_firmware($$$$)
        write_hunk(807864, 192);
 
        #
-       # Firmware 60, type: SCODE FW  DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
+       # Firmware 60, type: SCODE FW  DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x62000100);                 # Type
+       write_le32(0x620003e0);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(4760);                       # IF
        write_le32(192);                        # Size
@@ -726,30 +726,30 @@ sub main_firmware($$$$)
        write_hunk(811512, 192);
 
        #
-       # Firmware 62, type: SCODE FW  DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
+       # Firmware 62, type: SCODE FW  HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x62000080);                 # Type
+       write_le32(0x60000000);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5260);                       # IF
        write_le32(192);                        # Size
        write_hunk(810552, 192);
 
        #
-       # Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+       # Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000008, 0x00000007);     # ID
+       write_le64(0x0000000f, 0x00000007);     # ID
        write_le16(5320);                       # IF
        write_le32(192);                        # Size
        write_hunk(810744, 192);
 
        #
-       # Firmware 64, type: SCODE FW  DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
+       # Firmware 64, type: SCODE FW  DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x64000200);                 # Type
+       write_le32(0x65000380);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5400);                       # IF
        write_le32(192);                        # Size
@@ -766,50 +766,50 @@ sub main_firmware($$$$)
        write_hunk(809592, 192);
 
        #
-       # Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
+       # Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192
        #
 
        write_le32(0x60000000);                 # Type
-       write_le64(0x00000002, 0x00000007);     # ID
+       write_le64(0x00000003, 0x00000007);     # ID
        write_le16(5640);                       # IF
        write_le32(192);                        # Size
        write_hunk(808440, 192);
 
        #
-       # Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+       # Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192
        #
 
        write_le32(0x60000000);                 # Type
-       write_le64(0x00000008, 0x00000007);     # ID
+       write_le64(0x0000000c, 0x00000007);     # ID
        write_le16(5740);                       # IF
        write_le32(192);                        # Size
        write_hunk(808632, 192);
 
        #
-       # Firmware 68, type: SCODE FW  DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
+       # Firmware 68, type: SCODE FW  HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x61000080);                 # Type
+       write_le32(0x60000000);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(5900);                       # IF
        write_le32(192);                        # Size
        write_hunk(810360, 192);
 
        #
-       # Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
+       # Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000000, 0x00000010);     # ID
+       write_le64(0x0000000c, 0x04c000f0);     # ID
        write_le16(6000);                       # IF
        write_le32(192);                        # Size
        write_hunk(808824, 192);
 
        #
-       # Firmware 70, type: SCODE FW  DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
+       # Firmware 70, type: SCODE FW  DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192
        #
 
-       write_le32(0x68000060);                 # Type
+       write_le32(0x68050060);                 # Type
        write_le64(0x00000000, 0x00000000);     # ID
        write_le16(6200);                       # IF
        write_le32(192);                        # Size
@@ -846,11 +846,11 @@ sub main_firmware($$$$)
        write_hunk(809208, 192);
 
        #
-       # Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
+       # Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192
        #
 
        write_le32(0x60008000);                 # Type
-       write_le64(0x00000000, 0x04000000);     # ID
+       write_le64(0x0000000c, 0x044000e0);     # ID
        write_le16(6500);                       # IF
        write_le32(192);                        # Size
        write_hunk(811128, 192);
index 11950698a2e7529611080fcd83c475b1ccf9511e..128bb9cd5755f57f7a8cab9895149edcb39680aa 100644 (file)
@@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON
        depends on (I2C || I2C=n) && VIDEO_DEV
        default (I2C || I2C=n) && VIDEO_DEV
 
-config VIDEO_V4L1
+config VIDEO_ALLOW_V4L1
        bool "Enable Video For Linux API 1 (DEPRECATED)"
        depends on VIDEO_DEV && VIDEO_V4L2_COMMON
        default VIDEO_DEV && VIDEO_V4L2_COMMON
@@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT
          If you are unsure as to whether this is required, answer Y.
 
 config VIDEO_V4L2
-       bool
+       tristate
        depends on VIDEO_DEV && VIDEO_V4L2_COMMON
        default VIDEO_DEV && VIDEO_V4L2_COMMON
 
+config VIDEO_V4L1
+       tristate
+       depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+       default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
 source "drivers/media/video/Kconfig"
 
 source "drivers/media/radio/Kconfig"
@@ -155,7 +160,7 @@ config VIDEOBUF_GEN
        tristate
 
 config VIDEOBUF_DMA_SG
-       depends on PCI
+       depends on HAS_DMA
        select VIDEOBUF_GEN
        tristate
 
index bb2a027b94837d40740503ad50a94dbb71dc2b74..2665052079258c6d015cc42f7109bfd1d11f6b8c 100644 (file)
@@ -34,7 +34,7 @@ static int repeat = 1;
 module_param(repeat, int, 0444);
 MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
 
-static int debug = 0;    /* debug level (0,1,2) */
+static int debug;    /* debug level (0,1,2) */
 module_param(debug, int, 0644);
 
 #define dprintk(level, fmt, arg...)    if (debug >= level) \
index 2ab5a120470d98569a6f922afd08a463c446566a..a3485817e46c9e06b765bda262fdd9f8215b7168 100644 (file)
@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_pixelview);
 
+/*
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+   present on PV MPEG 8000GT
+ */
+IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
+       [0x3c] = KEY_PAUSE,             /* Timeshift */
+       [0x12] = KEY_POWER,
+
+       [0x3d] = KEY_1,
+       [0x38] = KEY_2,
+       [0x18] = KEY_3,
+       [0x35] = KEY_4,
+       [0x39] = KEY_5,
+       [0x15] = KEY_6,
+       [0x36] = KEY_7,
+       [0x3a] = KEY_8,
+       [0x1e] = KEY_9,
+       [0x3e] = KEY_0,
+
+       [0x1c] = KEY_AGAIN,             /* LOOP */
+       [0x3f] = KEY_MEDIA,             /* Source */
+       [0x1f] = KEY_LAST,              /* +100 */
+       [0x1b] = KEY_MUTE,
+
+       [0x17] = KEY_CHANNELDOWN,
+       [0x16] = KEY_CHANNELUP,
+       [0x10] = KEY_VOLUMEUP,
+       [0x14] = KEY_VOLUMEDOWN,
+       [0x13] = KEY_ZOOM,
+
+       [0x19] = KEY_SHUFFLE,           /* SNAPSHOT */
+       [0x1a] = KEY_SEARCH,            /* scan */
+
+       [0x37] = KEY_REWIND,            /* << */
+       [0x32] = KEY_RECORD,            /* o (red) */
+       [0x33] = KEY_FORWARD,           /* >> */
+       [0x11] = KEY_STOP,              /* square */
+       [0x3b] = KEY_PLAY,              /* > */
+       [0x30] = KEY_PLAYPAUSE,         /* || */
+
+       [0x31] = KEY_TV,
+       [0x34] = KEY_RADIO,
+};
+EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
+
 IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
        [ 0x00 ] = KEY_0,
        [ 0x01 ] = KEY_1,
@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
        [ 0x12 ] = KEY_CHANNELUP,    // Channel +
        [ 0x13 ] = KEY_CHANNELDOWN,  // Channel -
        [ 0x06 ] = KEY_AGAIN,        // Recall
-       [ 0x10 ] = KEY_ENTER,      // Enter
+       [ 0x10 ] = KEY_ENTER,        // Enter
+
+       [ 0x19 ] = KEY_BACK,         // Rewind  ( <<< )
+       [ 0x1f ] = KEY_FORWARD,      // Forward ( >>> )
+       [ 0x0a ] = KEY_ANGLE,        // (no label, may be used as the PAUSE button)
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
 
 /* Mapping for the 28 key remote control as seen at
    http://www.sednacomputer.com/photo/cardbus-tv.jpg
-   Pavel Mihaylov <bin@bash.info> */
+   Pavel Mihaylov <bin@bash.info>
+   Also for the remote bundled with Kozumi KTV-01C card */
 IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
        [ 0x00 ] = KEY_0,
        [ 0x01 ] = KEY_1,
@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
        [ 0x1c ] = KEY_RADIO,          /* FM Radio */
        [ 0x1d ] = KEY_RECORD,
        [ 0x1e ] = KEY_PAUSE,
+       /* additional codes for Kozumi's remote */
+       [0x14] = KEY_INFO,        /* OSD */
+       [0x16] = KEY_OK,          /* OK */
+       [0x17] = KEY_DIGITS,      /* Plus */
+       [0x1f] = KEY_PLAY,        /* Play */
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_behold);
 
+/* Beholder Intl. Ltd. 2008
+ * Dmitry Belimov d.belimov@google.com
+ * Keytable is used by BeholdTV Columbus
+ * The "ascii-art picture" below (in comments, first row
+ * is the keycode in hex, and subsequent row(s) shows
+ * the button labels (several variants when appropriate)
+ * helps to descide which keycodes to assign to the buttons.
+ */
+IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
+
+       /*  0x13   0x11   0x1C   0x12  *
+        *  Mute  Source  TV/FM  Power *
+        *                             */
+
+       [0x13] = KEY_MUTE,
+       [0x11] = KEY_PROPS,
+       [0x1C] = KEY_TUNER,     /* KEY_TV/KEY_RADIO */
+       [0x12] = KEY_POWER,
+
+       /*  0x01    0x02    0x03  0x0D    *
+        *   1       2       3   Stereo   *
+        *                                *
+        *  0x04    0x05    0x06  0x19    *
+        *   4       5       6   Snapshot *
+        *                                *
+        *  0x07    0x08    0x09  0x10    *
+        *   7       8       9    Zoom    *
+        *                                */
+       [0x01] = KEY_1,
+       [0x02] = KEY_2,
+       [0x03] = KEY_3,
+       [0x0D] = KEY_SETUP,       /* Setup key */
+       [0x04] = KEY_4,
+       [0x05] = KEY_5,
+       [0x06] = KEY_6,
+       [0x19] = KEY_BOOKMARKS, /* Snapshot key */
+       [0x07] = KEY_7,
+       [0x08] = KEY_8,
+       [0x09] = KEY_9,
+       [0x10] = KEY_ZOOM,
+
+       /*  0x0A    0x00    0x0B       0x0C   *
+        * RECALL    0    ChannelUp  VolumeUp *
+        *                                    */
+       [0x0A] = KEY_AGAIN,
+       [0x00] = KEY_0,
+       [0x0B] = KEY_CHANNELUP,
+       [0x0C] = KEY_VOLUMEUP,
+
+       /*   0x1B      0x1D      0x15        0x18     *
+        * Timeshift  Record  ChannelDown  VolumeDown *
+        *                                            */
+
+       [0x1B] = KEY_REWIND,
+       [0x1D] = KEY_RECORD,
+       [0x15] = KEY_CHANNELDOWN,
+       [0x18] = KEY_VOLUMEDOWN,
+
+       /*   0x0E   0x1E     0x0F     0x1A  *
+        *   Stop   Pause  Previouse  Next  *
+        *                                  */
+
+       [0x0E] = KEY_STOP,
+       [0x1E] = KEY_PAUSE,
+       [0x0F] = KEY_PREVIOUS,
+       [0x1A] = KEY_NEXT,
+
+};
+EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
+
 /*
  * Remote control for the Genius TVGO A11MCE
  * Adrian Pardini <pardo.bsso@gmail.com>
@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
        [0x50] = KEY_BLUE,
 };
 EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
+
+/*
+ * Remote control for Powercolor Real Angel 330
+ * Daniel Fraga <fragabr@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
+       [0x38] = KEY_SWITCHVIDEOMODE,   /* switch inputs */
+       [0x0c] = KEY_MEDIA,             /* Turn ON/OFF App */
+       [0x00] = KEY_0,
+       [0x01] = KEY_1,
+       [0x02] = KEY_2,
+       [0x03] = KEY_3,
+       [0x04] = KEY_4,
+       [0x05] = KEY_5,
+       [0x06] = KEY_6,
+       [0x07] = KEY_7,
+       [0x08] = KEY_8,
+       [0x09] = KEY_9,
+       [0x0a] = KEY_DIGITS,            /* single, double, tripple digit */
+       [0x29] = KEY_PREVIOUS,          /* previous channel */
+       [0x12] = KEY_BRIGHTNESSUP,
+       [0x13] = KEY_BRIGHTNESSDOWN,
+       [0x2b] = KEY_MODE,              /* stereo/mono */
+       [0x2c] = KEY_TEXT,              /* teletext */
+       [0x20] = KEY_UP,                /* channel up */
+       [0x21] = KEY_DOWN,              /* channel down */
+       [0x10] = KEY_RIGHT,             /* volume up */
+       [0x11] = KEY_LEFT,              /* volume down */
+       [0x0d] = KEY_MUTE,
+       [0x1f] = KEY_RECORD,
+       [0x17] = KEY_PLAY,
+       [0x16] = KEY_PAUSE,
+       [0x0b] = KEY_STOP,
+       [0x27] = KEY_FASTFORWARD,
+       [0x26] = KEY_REWIND,
+       [0x1e] = KEY_SEARCH,            /* autoscan */
+       [0x0e] = KEY_SHUFFLE,           /* snapshot */
+       [0x2d] = KEY_SETUP,
+       [0x0f] = KEY_SCREEN,            /* full screen */
+       [0x14] = KEY_RADIO,             /* FM radio */
+       [0x25] = KEY_POWER,             /* power */
+};
+EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
index 7707b8c7394b17308c067b2813f6809e105c5072..89c7660b85d66cf4dc84c6da4baa9ba14461bd0e 100644 (file)
@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
                if (err) {
                        printk(KERN_ERR "%s: %s timed out while waiting for "
                                        "registers getting programmed\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
                saa7146_read(dev, MC2);
                if (err) {
                        DEB_S(("%s: %s timed out while waiting for transfer "
-                               "completion\n", dev->name, __FUNCTION__));
+                               "completion\n", dev->name, __func__));
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
                if (!loops--) {
                        printk(KERN_ERR "%s: %s timed out while waiting for "
                                        "registers getting programmed\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                        return -ETIMEDOUT;
                }
                udelay(1);
@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
                saa7146_read(dev, MC2);
                if (!loops--) {
                        DEB_S(("%s: %s timed out while waiting for transfer "
-                               "completion\n", dev->name, __FUNCTION__));
+                               "completion\n", dev->name, __func__));
                        return -ETIMEDOUT;
                }
                udelay(5);
index 7e7689afae629c0a012979dc56a2dc6f30ade7d3..35b01ec40a5139d6e48b675338bd057360a0a79c 100644 (file)
@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                return -ERESTARTSYS;
 
                        printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
-                               dev->name, __FUNCTION__);
+                               dev->name, __func__);
                        return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                        }
                        if (time_after(jiffies,timeout)) {
                                printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                                return -EIO;
                        }
                }
@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                 * (no answer from nonexisistant device...)
                                 */
                                printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
-                                       dev->name, __FUNCTION__);
+                                       dev->name, __func__);
                                return -EIO;
                        }
                        if (++trial < 50 && short_delay)
index bfbd5a841ebf9f621642b60d1ca0324a650c6b84..74e2b56ecb5bb09b13135640872efb32445165b3 100644 (file)
@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
        fh->vbi_fmt.start[1] = 312;
        fh->vbi_fmt.count[1] = 16;
 
-       videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
                            sizeof(struct saa7146_buf),
index 66fdbd0e6a6ddfe5ad7f5a6a72045e574db95d56..3cbc6ebbe64939b5d7239dd40caa4b6ab38c58f0 100644 (file)
@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
        sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
-       videobuf_queue_pci_init(&fh->video_q, &video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->video_q, &video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct saa7146_buf),
index 3197aeb61d1f88181261e3db244b8531e64f9706..6ec5afba1ca7ee061779067f22b36ad352d43b96 100644 (file)
@@ -9,6 +9,11 @@ config DVB_B2C2_FLEXCOP
        select DVB_STV0297 if !DVB_FE_CUSTOMISE
        select DVB_BCM3510 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select DVB_S5H1420 if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
+       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select DVB_CX24123 if !DVB_FE_CUSTOMISE
        help
          Support for the digital TV receiver chip made by B2C2 Inc. included in
          Technisats PCI cards and USB boxes.
index e97ff60a1eff820c1c8df35d8d593c5d24240dfe..870e2848c2962418b343ef2ae4ae5fcc561c0a5d 100644 (file)
@@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
        flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
 
+
 ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
 b2c2-flexcop-objs += flexcop-dma.o
 endif
@@ -13,3 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/video/
index 5a6c4fe249e7b5bd190c1a062e4f28320c022534..8ce06336e76f88372b83bc0297915b5c048238ca 100644 (file)
@@ -44,6 +44,14 @@ struct flexcop_dma {
        u32 size; /* size of each address in bytes */
 };
 
+struct flexcop_i2c_adapter {
+       struct flexcop_device *fc;
+       struct i2c_adapter i2c_adap;
+
+       u8 no_base_addr;
+       flexcop_i2c_port_t port;
+};
+
 /* Control structure for data definitions that are common to
  * the B2C2-based PCI and USB devices.
  */
@@ -72,7 +80,7 @@ struct flexcop_device {
        struct dmx_frontend mem_frontend;
        int (*fe_sleep) (struct dvb_frontend *);
 
-       struct i2c_adapter i2c_adap;
+       struct flexcop_i2c_adapter fc_i2c_adap[3];
        struct mutex i2c_mutex;
        struct module *owner;
 
@@ -87,7 +95,8 @@ struct flexcop_device {
        int               (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
 
 
-       int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+       int (*i2c_request) (struct flexcop_i2c_adapter*,
+               flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
        int (*stream_control) (struct flexcop_device*, int);
 
        int (*get_mac_addr) (struct flexcop_device *fc, int extended);
@@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
  * one. We have it in flexcop-i2c.c, because it is going via the actual
  * I2C-channel of the flexcop.
  */
-int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
-                       flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
+       u8 chipaddr, u8 addr, u8 *buf, u16 len);
 
 /* from flexcop-sram.c */
 int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
index 6f592bc32d22ee136eb12fd0e4150af076370701..a91ed28f03a41d815f9edc2f32b7805535cf8ce1 100644 (file)
@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
 {
        flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
        flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-       deb_info("%s\n",__FUNCTION__);
+       deb_info("%s\n",__func__);
        v.dma_0xc.remap_enable = onoff;
        fc->write_ibi_reg(fc,r,v);
        return 0;
@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
 
        flexcop_dma_remap(fc,dma_idx,0);
 
-       deb_info("%s\n",__FUNCTION__);
+       deb_info("%s\n",__func__);
        v.dma_0x4_write.dmatimer = cycles;
        fc->write_ibi_reg(fc,r,v);
        return 0;
index bbcf070a178ddd95ef0e33f8024c6a80958010ee..8a8ae8a3e6ba6954717739ef59487d8804698297 100644 (file)
@@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
 {
        int i,ret = 0;
        u8 chipaddr =  0x50 | ((addr >> 8) & 3);
-       for (i = 0; i < retries; i++)
-               if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
+       for (i = 0; i < retries; i++) {
+               ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
+                       addr & 0xff, buf, len);
+               if (ret == 0)
                        break;
+       }
        return ret;
 }
 
 static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
 {
-       int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
+       int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
        if (ret == 0)
                if (calc_lrc(buf, len - 1) != buf[len - 1])
                        ret = -EINVAL;
index 0378fd64659141ec73933149637552d71aacc0f8..7b0ea3bdfafbf9c1b00080a0e3a97a3478bce212 100644 (file)
@@ -5,6 +5,8 @@
  *
  * see flexcop.c for copyright information.
  */
+#include <media/tuner.h>
+
 #include "flexcop.h"
 
 #include "stv0299.h"
 #include "mt312.h"
 #include "lgdt330x.h"
 #include "dvb-pll.h"
+#include "tuner-simple.h"
+
+#include "s5h1420.h"
+#include "itd1000.h"
+
+#include "cx24123.h"
+#include "cx24113.h"
+
+#include "isl6421.h"
 
 /* lnb control */
 
@@ -180,13 +191,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
        buf[2] = 0x84;  /* 0xC4 */
        buf[3] = 0x08;
 
-       if (params->frequency < 1500000) buf[3] |= 0x10;
+       if (params->frequency < 1500000)
+               buf[3] |= 0x10;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
+       if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
                return -EIO;
-       }
        return 0;
 }
 
@@ -241,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_LK,
+       .lock_output = STV0299_LOCKOUTPUT_LK,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
@@ -337,7 +348,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe,
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -386,10 +397,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
        deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
-       ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
+       ret = fc->i2c_request(&fc->fc_i2c_adap[2],
+               FC_WRITE, 0x61, buf[0], &buf[1], 3);
        deb_tuner("tuner write returned: %d\n",ret);
 
-       return 0;
+       return ret;
 }
 
 static u8 alps_tdee4_stv0297_inittab[] = {
@@ -472,56 +484,159 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
 //     .pll_set = alps_tdee4_stv0297_pll_set,
 };
 
+
+/* SkyStar2 rev2.7 (a/u) */
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+       .demod_address = 0x53,
+       .invert = 1,
+       .repeated_start_workaround = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+       .i2c_address = 0x61,
+};
+
+/* SkyStar2 rev2.8 */
+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
+       .demod_address = 0x55,
+       .dont_use_pll = 1,
+       .agc_callback = cx24113_agc_callback,
+};
+
+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
+       .i2c_addr = 0x54,
+       .xtal_khz = 10111,
+};
+
 /* try to figure out the frontend, each card/box can have on of the following list */
 int flexcop_frontend_init(struct flexcop_device *fc)
 {
        struct dvb_frontend_ops *ops;
+       struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
+       struct i2c_adapter *i2c_tuner;
+
+       /* enable no_base_addr - no repeated start when reading */
+       fc->fc_i2c_adap[0].no_base_addr = 1;
+       fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
+       if (fc->fe != NULL) {
+               flexcop_ibi_value r108;
+               i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+               ops = &fc->fe->ops;
+
+               fc->fe_sleep = ops->sleep;
+               ops->sleep   = flexcop_sleep;
+
+               fc->dev_type = FC_SKY_REV27;
+
+               /* enable no_base_addr - no repeated start when reading */
+               fc->fc_i2c_adap[2].no_base_addr = 1;
+               if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
+                       err("ISL6421 could NOT be attached");
+               else
+                       info("ISL6421 successfully attached");
+
+               /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
+               r108.raw = 0x00000506;
+               fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+               if (i2c_tuner) {
+                       if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
+                               err("ITD1000 could NOT be attached");
+                       else
+                               info("ITD1000 successfully attached");
+               }
+               goto fe_found;
+       }
+       fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
+
+       /* try the sky v2.8 (cx24123, isl6421) */
+       fc->fe = dvb_attach(cx24123_attach,
+               &skystar2_rev2_8_cx24123_config, i2c);
+       if (fc->fe != NULL) {
+               i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
+               if (i2c_tuner != NULL) {
+                       if (dvb_attach(cx24113_attach, fc->fe,
+                                       &skystar2_rev2_8_cx24113_config,
+                                       i2c_tuner) == NULL)
+                               err("CX24113 could NOT be attached");
+                       else
+                               info("CX24113 successfully attached");
+               }
+
+               fc->dev_type = FC_SKY_REV28;
+
+               fc->fc_i2c_adap[2].no_base_addr = 1;
+               if (dvb_attach(isl6421_attach, fc->fe,
+                      &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
+                       err("ISL6421 could NOT be attached");
+               else
+                       info("ISL6421 successfully attached");
+
+               /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
+                * IR-receiver (PIC16F818) - but the card has no input for
+                * that ??? */
+
+               goto fe_found;
+    }
 
        /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-       if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
+       fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
+       if (fc->fe != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
 
                ops->set_voltage = flexcop_set_voltage;
 
-               fc->fe_sleep             = ops->sleep;
-               ops->sleep               = flexcop_sleep;
+               fc->fe_sleep = ops->sleep;
+               ops->sleep = flexcop_sleep;
+
+               fc->dev_type = FC_SKY;
+               goto fe_found;
+       }
 
-               fc->dev_type          = FC_SKY;
-               info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
-       } else
        /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-       if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
-               fc->dev_type          = FC_AIR_DVB;
+       fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_DVB;
                fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
-               info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
        /* try the air atsc 2nd generation (nxt2002) */
-       if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC2;
+       fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC2;
                dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
-               info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
-       } else
-       /* try the air atsc 3nd generation (lgdt3303) */
-       if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC3;
-               dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
-               info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
+       fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC3;
+               dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+                               TUNER_LG_TDVS_H06XF);
+               goto fe_found;
+       }
+
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-       if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type          = FC_AIR_ATSC1;
-               info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
-       } else
+       fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_AIR_ATSC1;
+               goto fe_found;
+       }
+
        /* try the cable dvb (stv0297) */
-       if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
-               fc->dev_type                        = FC_CABLE;
+       fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
+       if (fc->fe != NULL) {
+               fc->dev_type = FC_CABLE;
                fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
-               info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
-       } else
+               goto fe_found;
+       }
+
        /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-       if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+       fc->fe = dvb_attach(vp310_mt312_attach,
+               &skystar23_samsung_tbdu18132_config, i2c);
+       if (fc->fe != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
@@ -535,19 +650,21 @@ int flexcop_frontend_init(struct flexcop_device *fc)
                ops->sleep                  = flexcop_sleep;
 
                fc->dev_type                = FC_SKY_OLD;
-               info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
+               goto fe_found;
        }
 
-       if (fc->fe == NULL) {
-               err("no frontend driver found for this B2C2/FlexCop adapter");
-               return -ENODEV;
-       } else {
-               if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
-                       err("frontend registration failed!");
-                       dvb_frontend_detach(fc->fe);
-                       fc->fe = NULL;
-                       return -EINVAL;
-               }
+       err("no frontend driver found for this B2C2/FlexCop adapter");
+       return -ENODEV;
+
+fe_found:
+       info("found '%s' .", fc->fe->ops.info.name);
+       if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+               err("frontend registration failed!");
+               ops = &fc->fe->ops;
+               if (ops->release != NULL)
+                       ops->release(fc->fe);
+               fc->fe = NULL;
+               return -EINVAL;
        }
        fc->init_state |= FC_STATE_FE_INIT;
        return 0;
index 6bf858a436c98048653f1a6a0ef9eb9305709584..55973eaf371180d90534bced637142582e5373bc 100644 (file)
@@ -9,6 +9,8 @@
 
 #define FC_MAX_I2C_RETRIES 100000
 
+/* #define DUMP_I2C_MESSAGES */
+
 static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
 {
        int i;
@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
        return -EREMOTEIO;
 }
 
-static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
+static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
+       flexcop_ibi_value r100, u8 *buf)
 {
        flexcop_ibi_value r104;
        int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
                ret;
 
-       if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-               /* The Cablestar needs a different kind of i2c-transfer (does not
-                * support "Repeat Start"):
-                * wait for the ACK failure,
-                * and do a subsequent read with the Bit 30 enabled
-                */
-               r100.tw_sm_c_100.no_base_addr_ack_error = 1;
-               if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
-                       deb_i2c("no_base_addr read failed. %d\n",ret);
-                       return ret;
-               }
+       r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
+       ret = flexcop_i2c_operation(i2c->fc, &r100);
+       if (ret != 0) {
+               deb_i2c("read failed. %d\n", ret);
+               return ret;
        }
 
        buf[0] = r100.tw_sm_c_100.data1_reg;
 
        if (len > 0) {
-               r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
-               deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+               r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
+               deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
 
                /* there is at least one more byte, otherwise we wouldn't be here */
                buf[1] = r104.tw_sm_c_104.data2_reg;
@@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
        r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
        r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
 
-       deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+       deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
 
        /* write the additional i2c data before doing the actual i2c operation */
-       fc->write_ibi_reg(fc,tw_sm_c_104,r104);
-       return flexcop_i2c_operation(fc,&r100);
+       fc->write_ibi_reg(fc, tw_sm_c_104, r104);
+       return flexcop_i2c_operation(fc, &r100);
 }
 
-int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
+       flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
        int ret;
+
+#ifdef DUMP_I2C_MESSAGES
+       int i;
+#endif
+
        u16 bytes_to_transfer;
        flexcop_ibi_value r100;
 
@@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
        r100.raw = 0;
        r100.tw_sm_c_100.chipaddr = chipaddr;
        r100.tw_sm_c_100.twoWS_rw = op;
-       r100.tw_sm_c_100.twoWS_port_reg = port;
+       r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
+
+#ifdef DUMP_I2C_MESSAGES
+       printk(KERN_DEBUG "%d ", i2c->port);
+       if (op == FC_READ)
+               printk("rd(");
+       else
+               printk("wr(");
+
+       printk("%02x): %02x ", chipaddr, addr);
+#endif
+
+       /* in that case addr is the only value ->
+        * we write it twice as baseaddr and val0
+        * BBTI is doing it like that for ISL6421 at least */
+       if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
+               buf = &addr;
+               len = 1;
+       }
 
        while (len != 0) {
                bytes_to_transfer = len > 4 ? 4 : len;
@@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
                r100.tw_sm_c_100.baseaddr = addr;
 
                if (op == FC_READ)
-                       ret = flexcop_i2c_read4(fc, r100, buf);
+                       ret = flexcop_i2c_read4(i2c, r100, buf);
                else
-                       ret = flexcop_i2c_write4(fc,r100, buf);
+                       ret = flexcop_i2c_write4(i2c->fc, r100, buf);
+
+#ifdef DUMP_I2C_MESSAGES
+               for (i = 0; i < bytes_to_transfer; i++)
+                       printk("%02x ", buf[i]);
+#endif
 
                if (ret < 0)
                        return ret;
@@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
                buf  += bytes_to_transfer;
                addr += bytes_to_transfer;
                len  -= bytes_to_transfer;
-       };
+       }
+
+#ifdef DUMP_I2C_MESSAGES
+       printk("\n");
+#endif
 
        return 0;
 }
@@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request);
 /* master xfer callback for demodulator */
 static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
 {
-       struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
+       struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
        int i, ret = 0;
 
        /* Some drivers use 1 byte or 0 byte reads as probes, which this
@@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
        if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
                return 1;
 
-       if (mutex_lock_interruptible(&fc->i2c_mutex))
+       if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
                return -ERESTARTSYS;
 
-       /* reading */
-       if (num == 2 &&
-               msgs[0].flags == 0 &&
-               msgs[1].flags == I2C_M_RD &&
-               msgs[0].buf != NULL &&
-               msgs[1].buf != NULL) {
-
-               ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
-
-       } else for (i = 0; i < num; i++) { /* writing command */
-               if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) {
-                       ret = -EINVAL;
+       for (i = 0; i < num; i++) {
+               /* reading */
+               if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
+                       ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
+                               msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len);
+                       i++; /* skip the following message */
+               } else /* writing */
+                       ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
+                               msgs[i].buf[0], &msgs[i].buf[1],
+                               msgs[i].len - 1);
+               if (ret < 0) {
+                       err("i2c master_xfer failed");
                        break;
                }
-
-               ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
        }
 
-       if (ret < 0)
-               err("i2c master_xfer failed");
-       else
-               ret = num;
-
-       mutex_unlock(&fc->i2c_mutex);
+       mutex_unlock(&i2c->fc->i2c_mutex);
 
+       if (ret == 0)
+               ret = num;
        return ret;
 }
 
@@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc)
 
        mutex_init(&fc->i2c_mutex);
 
-       memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
-       strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
-               sizeof(fc->i2c_adap.name));
-
-       i2c_set_adapdata(&fc->i2c_adap,fc);
+       fc->fc_i2c_adap[0].fc = fc;
+       fc->fc_i2c_adap[1].fc = fc;
+       fc->fc_i2c_adap[2].fc = fc;
+
+       fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
+       fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
+       fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
+
+       strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
+               "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
+       strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
+               "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
+       strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
+               "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
+
+       i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
+       i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
+       i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
+
+       fc->fc_i2c_adap[0].i2c_adap.class =
+               fc->fc_i2c_adap[1].i2c_adap.class =
+               fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+       fc->fc_i2c_adap[0].i2c_adap.algo =
+               fc->fc_i2c_adap[1].i2c_adap.algo =
+               fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
+       fc->fc_i2c_adap[0].i2c_adap.algo_data =
+               fc->fc_i2c_adap[1].i2c_adap.algo_data =
+               fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
+       fc->fc_i2c_adap[0].i2c_adap.dev.parent =
+               fc->fc_i2c_adap[1].i2c_adap.dev.parent =
+               fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
+
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+       if (ret < 0)
+               return ret;
 
-       fc->i2c_adap.class          = I2C_CLASS_TV_DIGITAL;
-       fc->i2c_adap.algo       = &flexcop_algo;
-       fc->i2c_adap.algo_data  = NULL;
-       fc->i2c_adap.dev.parent = fc->dev;
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+       if (ret < 0)
+               goto adap_1_failed;
 
-       if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
-               return ret;
+       ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+       if (ret < 0)
+               goto adap_2_failed;
 
        fc->init_state |= FC_STATE_I2C_INIT;
        return 0;
+
+adap_2_failed:
+       i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+adap_1_failed:
+       i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+
+       return ret;
 }
 
 void flexcop_i2c_exit(struct flexcop_device *fc)
 {
-       if (fc->init_state & FC_STATE_I2C_INIT)
-               i2c_del_adapter(&fc->i2c_adap);
+       if (fc->init_state & FC_STATE_I2C_INIT) {
+               i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+               i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+               i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+       }
 
        fc->init_state &= ~FC_STATE_I2C_INIT;
 }
index 167583bf0621879b1f9deefd1c443646ccbd4771..93d20e56f909e17c243c8348e81e01047937e213 100644 (file)
@@ -52,6 +52,8 @@ static const char *flexcop_device_names[] = {
        "Sky2PC/SkyStar 2 DVB-S (old version)",
        "Cable2PC/CableStar 2 DVB-C",
        "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+       "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+       "Sky2PC/SkyStar 2 DVB-S rev 2.8",
 };
 
 static const char *flexcop_bus_names[] = {
index 01af4d237eb13b585ba6f8136494c07a3a17f27c..5b30dfc7846b2fbbe870efb38901e311c3bc2375 100644 (file)
@@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus
 #define deb_irq(args...)   dprintk(0x08,args)
 #define deb_chk(args...)   dprintk(0x10,args)
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
 
index 491f9bd6e1951be8d23463667da4fb5c72972b81..7599fccc1a5b80a438e9cbfd2c8d387c9b526f6c 100644 (file)
@@ -25,6 +25,8 @@ typedef enum {
        FC_SKY_OLD,
        FC_CABLE,
        FC_AIR_ATSC3,
+       FC_SKY_REV27,
+       FC_SKY_REV28,
 } flexcop_device_type_t;
 
 typedef enum {
index 01570ec80962ea7628596cb9fef36d615807b3e3..cda69528548ac9d0d9757f47786cbf732491a37f 100644 (file)
@@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                write_reg_dw(adapter, 0x700, command);
 
@@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                write_reg_dw(adapter, 0x700, command);
 
@@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
                };
 
                if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
+                       printk("%s: SRAM timeout\n", __func__);
 
                value = read_reg_dw(adapter, 0x700) >> 0x10;
 
@@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter)
 
                adapter->dw_sram_type = tmp & 0x30000;
 
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+               ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
 
        } else {
 
                adapter->dw_sram_type = 0x10000;
 
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+               ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
        }
 
        /* return value is never used? */
@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
 {
        u8 tmp1, tmp2;
 
-       dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+       dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
 
        sram_set_size(adapter, mask);
        sram_init(adapter);
@@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
        sram_read(adapter, addr, &tmp2, 1);
        sram_read(adapter, addr, &tmp2, 1);
 
-       dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
+       dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
 
        if (tmp2 != 0xa5)
                return 0;
@@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
        sram_read(adapter, addr, &tmp2, 1);
        sram_read(adapter, addr, &tmp2, 1);
 
-       dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
+       dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
 
        if (tmp2 != 0x5a)
                return 0;
@@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
 
        tmp3 = read_reg_dw(adapter, 0x71c);
 
-       dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+       dprintk("%s: tmp3 = %x\n", __func__, tmp3);
 
        write_reg_dw(adapter, 0x71c, tmp2);
 
@@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+               dprintk("%s: sram size = 32K\n", __func__);
 
                return 32;
        }
@@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 128K\n", __FUNCTION__);
+               dprintk("%s: sram size = 128K\n", __func__);
 
                return 128;
        }
@@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 64K\n", __FUNCTION__);
+               dprintk("%s: sram size = 64K\n", __func__);
 
                return 64;
        }
@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
                sram_init(adapter);
                write_reg_dw(adapter, 0x208, tmp);
 
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+               dprintk("%s: sram size = 32K\n", __func__);
 
                return 32;
        }
@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
        sram_init(adapter);
        write_reg_dw(adapter, 0x208, tmp);
 
-       dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+       dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
 
        return 0;
 }
index 87fb75f0d1cf0b88eb6e16706d8dfe3ffc3b7ebc..449fb5c3d0b1ed31f078ff9b8eb2c244ae4c10bf 100644 (file)
@@ -211,10 +211,11 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
 #endif
 
 /* usb i2c stuff */
-static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
+               u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
 {
+       struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
        u16 wValue, wIndex;
        int nWaitTime,pipe,len;
 //     u8 dwRequestType;
@@ -242,7 +243,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
                        deb_info("unsupported function for i2c_req %x\n",func);
                        return -EINVAL;
        }
-       wValue = (func << 8 ) | (port << 4);
+       wValue = (func << 8) | (i2c->port << 4);
        wIndex = (chipaddr << 8 ) | addr;
 
        deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
@@ -274,13 +275,15 @@ static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
        return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
 }
 
-static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
-               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
+       flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
        if (op == FC_READ)
-               return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
+               return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
+                       USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
        else
-               return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
+               return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
+                       USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
 }
 
 static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
index 2ddafd071c9776ddf02946f6ce018f86504e1fa0..5f79c8dc383651aa9349e3445f854d24947aab9a 100644 (file)
@@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
 #undef DEBSTATUS
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* global zero for ibi values */
 flexcop_ibi_value ibi_zero;
 
@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
-       int ret;
-       if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
+       int ret = dvb_register_adapter(&fc->dvb_adapter,
+                                      "FlexCop Digital TV device", fc->owner,
+                                      fc->dev, adapter_nr);
+       if (ret < 0) {
                err("error registering DVB adapter");
                return ret;
        }
@@ -257,6 +261,12 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        if ((ret = flexcop_dvb_init(fc)))
                goto error;
 
+       /* i2c has to be done before doing EEProm stuff -
+        * because the EEProm is accessed via i2c */
+       ret = flexcop_i2c_init(fc);
+       if (ret)
+               goto error;
+
        /* do the MAC address reading after initializing the dvb_adapter */
        if (fc->get_mac_addr(fc, 0) == 0) {
                u8 *b = fc->dvb_adapter.proposed_mac;
@@ -266,10 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
        } else
                warn("reading of MAC address failed.\n");
 
-
-       if ((ret = flexcop_i2c_init(fc)))
-               goto error;
-
        if ((ret = flexcop_frontend_init(fc)))
                goto error;
 
index ea666174e98874a8d9bb5a3de78aac660e03bf4f..902c762e0b7fb8867bc1d62ea65f2e2a4ee5e9a3 100644 (file)
@@ -7,8 +7,8 @@ config DVB_BT8XX
        select DVB_CX24110 if !DVB_FE_CUSTOMISE
        select DVB_OR51211 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
index 84cf70504d17855ff8821aa0d6e6700c5ecded76..9d3e68b5d6ebc22e9b8fb4adfdbf42aa50784d20 100644 (file)
@@ -1,3 +1,6 @@
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
+EXTRA_CFLAGS += -Idrivers/media/video
index 307ff35bdf13a6226e6413c104ae7279d176f50d..75711bde23ad3675fe82f89bf6f4edf68d7db644 100644 (file)
@@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state)
 {
        int retval;
        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
-       //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+       //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
                state->decode_lock = state->decode_strength = state->decode_snr = 0;
                return 0;
index 50bc32a8bd5533921a9af2923cf618728a18db8b..0258451423ad876b53e3e2a9b94044cf1b7025c9 100644 (file)
 #define dprintk(x, y, z, format, arg...) do {                                          \
        if (z) {                                                                        \
                if      ((x > DST_CA_ERROR) && (x > y))                                 \
-                       printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);      \
+                       printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);  \
                else if ((x > DST_CA_NOTICE) && (x > y))                                \
-                       printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);   \
+                       printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);       \
                else if ((x > DST_CA_INFO) && (x > y))                                  \
-                       printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);     \
+                       printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
                else if ((x > DST_CA_DEBUG) && (x > y))                                 \
-                       printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);    \
+                       printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);        \
        } else {                                                                        \
                if (x > y)                                                              \
                        printk(format, ## arg);                                         \
@@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state)
        dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
        dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
                state->messages[7], (state->messages[8] << 8) | state->messages[9],
-               (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+               (state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
        dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
        // Transform dst message to correct application_info message
index dedd30a8356bbaad2f78ef936a8352413f4acf41..6afbfbbef0ce304885826365df8a40735c9a5ee7 100644 (file)
@@ -40,10 +40,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk( args... ) \
-       do \
+       do \
                if (debug) printk(KERN_DEBUG args); \
-       while (0)
+       while (0)
 
 #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 
@@ -609,8 +611,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                lgdt330x_reset(card);
                card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
                if (card->fe != NULL) {
-                       dvb_attach(dvb_pll_attach, card->fe, 0x61,
-                                  card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, card->fe,
+                                  card->i2c_adapter, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
                }
                break;
@@ -670,7 +673,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                state->dst_ca = NULL;
                /*      DST is not a frontend, attaching the ASIC       */
                if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
-                       printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
+                       printk("%s: Could not find a Twinhan DST.\n", __func__);
                        break;
                }
                /*      Attach other DST peripherals if any             */
@@ -692,8 +695,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        case BTTV_BOARD_PC_HDTV:
                card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
                if (card->fe != NULL)
-                       dvb_attach(dvb_pll_attach, card->fe, 0x61,
-                                  card->i2c_adapter, DVB_PLL_FCV1236D);
+                       dvb_attach(simple_tuner_attach, card->fe,
+                                  card->i2c_adapter, 0x61,
+                                  TUNER_PHILIPS_FCV1236D);
                break;
        }
 
@@ -715,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
        int result;
 
-       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
+       result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
+                                     THIS_MODULE, &card->bt->dev->dev,
+                                     adapter_nr);
+       if (result < 0) {
                printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
                return result;
        }
index 436880e68672fe752859135dbff42790fefd93f3..4499ed2ac0ed7339384663dc1b2a5f8f77d82224 100644 (file)
@@ -38,7 +38,7 @@
 #include "or51211.h"
 #include "lgdt330x.h"
 #include "zl10353.h"
-#include "dvb-pll.h"
+#include "tuner-simple.h"
 
 struct dvb_bt8xx_card {
        struct mutex lock;
index db08b0a8888afc5763e935a53e712844f8a217aa..f5010e8671b8476109b44df80e90a47079305302 100644 (file)
@@ -58,11 +58,13 @@ static int debug;
 module_param_named(debug, debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(level, args...)                                                \
 do {                                                                   \
        if ((debug & level)) {                                          \
                printk("%s: %s(): ", KBUILD_MODNAME,                    \
-                      __FUNCTION__);                                   \
+                      __func__);                                       \
                printk(args); }                                         \
 } while (0)
 
@@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
                return -ENOMEM;
        }
 
-       if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
+       err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
+                                  THIS_MODULE, &cinergyt2->udev->dev,
+                                  adapter_nr);
+       if (err < 0) {
                kfree(cinergyt2);
                return err;
        }
index 0c1d87c5227ab0bf3e903d95e3cc92ce982b6d98..b0d347daae47a889ba54f89b938ecd8dd3ee46a5 100644 (file)
@@ -80,6 +80,8 @@ enum dmx_success {
 #define        TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
                               payload (<=184 bytes per packet) to callback */
 #define TS_DECODER      4   /* send stream to built-in decoder (if present) */
+#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
+                              the demux device, not to the dvr device */
 
 /* PES type for filters which write to built-in decoder */
 /* these should be kept identical to the types in dmx.h */
index f94bc31e3b3334d020b7e5dc95759f25a3e70ca8..df5bef6a2517821c013c1aedbcae843ff7b278fa 100644 (file)
@@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
        struct dmxdev *dmxdev = dvbdev->priv;
        struct dmx_frontend *front;
 
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        if (mutex_lock_interruptible(&dmxdev->mutex))
                return -ERESTARTSYS;
@@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
        return ret;
 }
 
+static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
+                                     unsigned long size)
+{
+       struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
+       void *newmem;
+       void *oldmem;
+
+       dprintk("function : %s\n", __func__);
+
+       if (buf->size == size)
+               return 0;
+       if (!size)
+               return -EINVAL;
+
+       newmem = vmalloc(size);
+       if (!newmem)
+               return -ENOMEM;
+
+       oldmem = buf->data;
+
+       spin_lock_irq(&dmxdev->lock);
+       buf->data = newmem;
+       buf->size = size;
+
+       /* reset and not flush in case the buffer shrinks */
+       dvb_ringbuffer_reset(buf);
+       spin_unlock_irq(&dmxdev->lock);
+
+       vfree(oldmem);
+
+       return 0;
+}
+
 static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
                                               *dmxdevfilter, int state)
 {
@@ -271,28 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
                                      unsigned long size)
 {
        struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
-       void *mem;
+       void *newmem;
+       void *oldmem;
 
        if (buf->size == size)
                return 0;
+       if (!size)
+               return -EINVAL;
        if (dmxdevfilter->state >= DMXDEV_STATE_GO)
                return -EBUSY;
+
+       newmem = vmalloc(size);
+       if (!newmem)
+               return -ENOMEM;
+
+       oldmem = buf->data;
+
        spin_lock_irq(&dmxdevfilter->dev->lock);
-       mem = buf->data;
-       buf->data = NULL;
+       buf->data = newmem;
        buf->size = size;
-       dvb_ringbuffer_flush(buf);
+
+       /* reset and not flush in case the buffer shrinks */
+       dvb_ringbuffer_reset(buf);
        spin_unlock_irq(&dmxdevfilter->dev->lock);
-       vfree(mem);
 
-       if (buf->size) {
-               mem = vmalloc(dmxdevfilter->buffer.size);
-               if (!mem)
-                       return -ENOMEM;
-               spin_lock_irq(&dmxdevfilter->dev->lock);
-               buf->data = mem;
-               spin_unlock_irq(&dmxdevfilter->dev->lock);
-       }
+       vfree(oldmem);
+
        return 0;
 }
 
@@ -374,7 +411,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                return 0;
        }
 
-       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
+       if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
+           || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
                buffer = &dmxdevfilter->buffer;
        else
                buffer = &dmxdevfilter->dev->dvr_buffer;
@@ -550,7 +588,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                                                                   dvb_dmxdev_section_callback);
                        if (ret < 0) {
                                printk("DVB (%s): could not alloc feed\n",
-                                      __FUNCTION__);
+                                      __func__);
                                return ret;
                        }
 
@@ -558,7 +596,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                                              (para->flags & DMX_CHECK_CRC) ? 1 : 0);
                        if (ret < 0) {
                                printk("DVB (%s): could not set feed\n",
-                                      __FUNCTION__);
+                                      __func__);
                                dvb_dmxdev_feed_restart(filter);
                                return ret;
                        }
@@ -620,9 +658,10 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
 
                if (otype == DMX_OUT_TS_TAP)
                        ts_type |= TS_PACKET;
-
-               if (otype == DMX_OUT_TAP)
-                       ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
+               else if (otype == DMX_OUT_TSDEMUX_TAP)
+                       ts_type |= TS_PACKET | TS_DEMUX;
+               else if (otype == DMX_OUT_TAP)
+                       ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
 
                ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
                                                      tsfeed,
@@ -732,7 +771,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
                                 struct dmxdev_filter *dmxdevfilter,
                                 struct dmx_sct_filter_params *params)
 {
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        dvb_dmxdev_filter_stop(dmxdevfilter);
 
@@ -1007,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
+       unsigned long arg = (unsigned long)parg;
        int ret;
 
        if (mutex_lock_interruptible(&dmxdev->mutex))
@@ -1014,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case DMX_SET_BUFFER_SIZE:
-               // FIXME: implement
-               ret = 0;
+               ret = dvb_dvr_set_buffer_size(dmxdev, arg);
                break;
 
        default:
@@ -1038,7 +1077,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
        struct dmxdev *dmxdev = dvbdev->priv;
        unsigned int mask = 0;
 
-       dprintk("function : %s\n", __FUNCTION__);
+       dprintk("function : %s\n", __func__);
 
        poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 
index 89437fdab8befcd393578c57f8c44d9434787612..8cbdb0ec67e2e4d2cc8f8119a7bfeaddd0c8f9ab 100644 (file)
@@ -250,7 +250,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
        unsigned long timeout;
        unsigned long start;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* loop until timeout elapsed */
        start = jiffies;
@@ -263,7 +263,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
 
                /* if we got the flags, it was successful! */
                if (res & waitfor) {
-                       dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
+                       dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
                        return 0;
                }
 
@@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
                msleep(1);
        }
 
-       dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
+       dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
 
        /* if we get here, we've timed out */
        return -ETIMEDOUT;
@@ -297,7 +297,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
        int buf_size;
        u8 buf[2];
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* we'll be determining these during this function */
        ca->slot_info[slot].da_irq_supported = 0;
@@ -549,7 +549,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
 {
        int configoption;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set the config option */
        ca->pub->write_attribute_mem(ca->pub, slot,
@@ -587,7 +587,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
        u8 buf[HOST_LINK_BUF_SIZE];
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* check if we have space for a link buf in the rx_buffer */
        if (ebuf == NULL) {
@@ -708,7 +708,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
        int status;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
 
        // sanity check
@@ -785,7 +785,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
  */
 static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        ca->pub->slot_shutdown(ca->pub, slot);
        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
@@ -892,7 +892,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
 static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
 {
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        ca->wakeup = 1;
        mb();
@@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data)
        int pktcount;
        void *rxbuf;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* choose the correct initial delay */
        dvb_ca_en50221_thread_update_delay(ca);
@@ -1172,7 +1172,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
        int err = 0;
        int slot;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (cmd) {
        case CA_RESET:
@@ -1266,7 +1266,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
        unsigned long timeout;
        int written;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
        if (count < 2)
@@ -1401,7 +1401,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
        int pktlen;
        int dispose = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
        if (count < 2)
@@ -1490,7 +1490,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
        int err;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (!try_module_get(ca->pub->owner))
                return -EIO;
@@ -1534,7 +1534,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
        struct dvb_ca_private *ca = dvbdev->priv;
        int err;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* mark the CA device as closed */
        ca->open = 0;
@@ -1564,7 +1564,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
        int slot;
        int result = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
                mask |= POLLIN;
@@ -1626,7 +1626,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
        struct dvb_ca_private *ca = NULL;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (slot_count < 1)
                return -EINVAL;
@@ -1704,7 +1704,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
        struct dvb_ca_private *ca = pubca->private;
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* shutdown the thread if there was one */
        kthread_stop(ca->thread);
index 7959020f9317d2ee5f1f0824370ab730542f09c3..934e15fffc565f4660dfc5954a49d1346748d315 100644 (file)
@@ -368,7 +368,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 #define DVR_FEED(f)                                                    \
        (((f)->type == DMX_TYPE_TS) &&                                  \
        ((f)->feed.ts.is_filtering) &&                                  \
-       (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
+       (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
 
 static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 {
@@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (dvb_demux_feed_find(feed)) {
                printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
-                      __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __func__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
@@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (!(dvb_demux_feed_find(feed))) {
                printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
-                      __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __func__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
index 925cfa6221ad09d73e2831a6cadb2435a3747290..2dddd08c5445383cfe1b94352c94bda403147130 100644 (file)
@@ -135,7 +135,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
        struct dvb_frontend_event *e;
        int wp;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (mutex_lock_interruptible (&events->mtx))
                return;
@@ -171,7 +171,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dvb_fe_events *events = &fepriv->events;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (events->overflow) {
                events->overflow = 0;
@@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
 {
        int q2;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (locked)
                (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
@@ -329,7 +329,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 
        dprintk("%s: drift:%i inversion:%i auto_step:%i "
                "auto_sub_step:%i started_auto_step:%i\n",
-               __FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
+               __func__, fepriv->lnb_drift, fepriv->inversion,
                fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
 
        /* set the frontend itself */
@@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data)
        fe_status_t s;
        struct dvb_frontend_parameters *params;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        fepriv->check_wrapped = 0;
        fepriv->quality = 0;
@@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        fepriv->exit = 1;
        mb();
@@ -665,7 +665,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct task_struct *fe_thread;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (fepriv->thread) {
                if (!fepriv->exit)
@@ -763,7 +763,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int err = -EOPNOTSUPP;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (fepriv->exit)
                return -ENODEV;
@@ -895,7 +895,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        int i;
                        u8 last = 1;
                        if (dvb_frontend_debug)
-                               printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
+                               printk("%s switch command: 0x%04lx\n", __func__, cmd);
                        do_gettimeofday(&nexttime);
                        if (dvb_frontend_debug)
                                memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -919,7 +919,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        }
                        if (dvb_frontend_debug) {
                                printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
-                                       __FUNCTION__, fe->dvb->num);
+                                       __func__, fe->dvb->num);
                                for (i = 1; i < 10; i++)
                                        printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
                        }
@@ -1037,7 +1037,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        poll_wait (file, &fepriv->events.wait_queue, wait);
 
@@ -1054,7 +1054,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
                if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
@@ -1095,7 +1095,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY)
                fepriv->release_jiffies = jiffies;
@@ -1135,7 +1135,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
                .kernel_ioctl = dvb_frontend_ioctl
        };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (mutex_lock_interruptible(&frontend_mutex))
                return -ERESTARTSYS;
@@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
 int dvb_unregister_frontend(struct dvb_frontend* fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        mutex_lock(&frontend_mutex);
        dvb_frontend_stop (fe);
index 4c8b62e2c035246095e5fc6e750a3127e7a188b3..56d871cfd7fc23bf6406fca9f3f0482830c6b881 100644 (file)
@@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 #ifdef ULE_DEBUG
        /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
        static unsigned char ule_hist[100*TS_SZ];
-       static unsigned char *ule_where = ule_hist, ule_dump = 0;
+       static unsigned char *ule_where = ule_hist, ule_dump;
 #endif
 
        /* For all TS cells in current buffer.
@@ -965,17 +965,17 @@ static int dvb_net_feed_start(struct net_device *dev)
        struct dmx_demux *demux = priv->demux;
        unsigned char *mac = (unsigned char *) dev->dev_addr;
 
-       dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
+       dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
        mutex_lock(&priv->mutex);
        if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
-               printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
+               printk("%s: BUG %d\n", __func__, __LINE__);
 
        priv->secfeed=NULL;
        priv->secfilter=NULL;
        priv->tsfeed = NULL;
 
        if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
-               dprintk("%s: alloc secfeed\n", __FUNCTION__);
+               dprintk("%s: alloc secfeed\n", __func__);
                ret=demux->allocate_section_feed(demux, &priv->secfeed,
                                         dvb_net_sec_callback);
                if (ret<0) {
@@ -993,38 +993,38 @@ static int dvb_net_feed_start(struct net_device *dev)
                }
 
                if (priv->rx_mode != RX_MODE_PROMISC) {
-                       dprintk("%s: set secfilter\n", __FUNCTION__);
+                       dprintk("%s: set secfilter\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
                }
 
                switch (priv->rx_mode) {
                case RX_MODE_MULTI:
                        for (i = 0; i < priv->multi_num; i++) {
-                               dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
+                               dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
                                dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
                                                       priv->multi_macs[i], mask_normal);
                        }
                        break;
                case RX_MODE_ALL_MULTI:
                        priv->multi_num=1;
-                       dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+                       dprintk("%s: set multi_secfilter[0]\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
                                               mac_allmulti, mask_allmulti);
                        break;
                case RX_MODE_PROMISC:
                        priv->multi_num=0;
-                       dprintk("%s: set secfilter\n", __FUNCTION__);
+                       dprintk("%s: set secfilter\n", __func__);
                        dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
                        break;
                }
 
-               dprintk("%s: start filtering\n", __FUNCTION__);
+               dprintk("%s: start filtering\n", __func__);
                priv->secfeed->start_filtering(priv->secfeed);
        } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
                struct timespec timeout = { 0, 10000000 }; // 10 msec
 
                /* we have payloads encapsulated in TS */
-               dprintk("%s: alloc tsfeed\n", __FUNCTION__);
+               dprintk("%s: alloc tsfeed\n", __func__);
                ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
                if (ret < 0) {
                        printk("%s: could not allocate ts feed\n", dev->name);
@@ -1048,7 +1048,7 @@ static int dvb_net_feed_start(struct net_device *dev)
                        goto error;
                }
 
-               dprintk("%s: start filtering\n", __FUNCTION__);
+               dprintk("%s: start filtering\n", __func__);
                priv->tsfeed->start_filtering(priv->tsfeed);
        } else
                ret = -EINVAL;
@@ -1063,17 +1063,17 @@ static int dvb_net_feed_stop(struct net_device *dev)
        struct dvb_net_priv *priv = dev->priv;
        int i, ret = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        mutex_lock(&priv->mutex);
        if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
                if (priv->secfeed) {
                        if (priv->secfeed->is_filtering) {
-                               dprintk("%s: stop secfeed\n", __FUNCTION__);
+                               dprintk("%s: stop secfeed\n", __func__);
                                priv->secfeed->stop_filtering(priv->secfeed);
                        }
 
                        if (priv->secfilter) {
-                               dprintk("%s: release secfilter\n", __FUNCTION__);
+                               dprintk("%s: release secfilter\n", __func__);
                                priv->secfeed->release_filter(priv->secfeed,
                                                              priv->secfilter);
                                priv->secfilter=NULL;
@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
                        for (i=0; i<priv->multi_num; i++) {
                                if (priv->multi_secfilter[i]) {
                                        dprintk("%s: release multi_filter[%d]\n",
-                                               __FUNCTION__, i);
+                                               __func__, i);
                                        priv->secfeed->release_filter(priv->secfeed,
                                                                      priv->multi_secfilter[i]);
                                        priv->multi_secfilter[i] = NULL;
@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
        } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
                if (priv->tsfeed) {
                        if (priv->tsfeed->is_filtering) {
-                               dprintk("%s: stop tsfeed\n", __FUNCTION__);
+                               dprintk("%s: stop tsfeed\n", __func__);
                                priv->tsfeed->stop_filtering(priv->tsfeed);
                        }
                        priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
index ac9d93cf83c6c898d48a6dd17622ce40e6d42094..872985b7912d3db12036abd78380a012012033e1 100644 (file)
@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
        rbuf->error = 0;
 }
 
-
+void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
+{
+       rbuf->pread = rbuf->pwrite = 0;
+       rbuf->error = 0;
+}
 
 void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
 {
index d97714e757362b6ee62204de6444b68337faaede..890826262966c16c709815d83e1e08ac68c08058 100644 (file)
@@ -69,6 +69,7 @@ struct dvb_ringbuffer {
 **     to lock read or write operations.
 **     Two or more readers must be locked against each other.
 **     Flushing the buffer counts as a read operation.
+**     Resetting the buffer counts as a read and write operation.
 **     Two or more writers must be locked against each other.
 */
 
@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
 extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
 
 
+/*
+** Reset the read and write pointers to zero and flush the buffer
+** This counts as a read and write operation
+*/
+extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
+
+
 /* read routines & macros */
 /* ---------------------- */
 /* flush buffer */
index 18738faecbbc51adc7f9311c066779cafdee0b88..8b56d929f7fd52c63f1fbda3165bcce33d0aa11d 100644 (file)
@@ -49,7 +49,6 @@ static const char * const dnames[] = {
        "net", "osd"
 };
 
-#define DVB_MAX_ADAPTERS       8
 #define DVB_MAX_IDS            4
 #define nums2minor(num,type,id)        ((num << 6) | (id << 4) | type)
 #define MAX_DVB_MINORS         (DVB_MAX_ADAPTERS*64)
@@ -97,7 +96,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
 }
 
 
-static struct file_operations dvb_device_fops =
+static const struct file_operations dvb_device_fops =
 {
        .owner =        THIS_MODULE,
        .open =         dvb_device_open,
@@ -196,7 +195,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        if ((id = dvbdev_get_free_id (adap, type)) < 0){
                mutex_unlock(&dvbdev_register_lock);
                *pdvbdev = NULL;
-               printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
+               printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
                return -ENFILE;
        }
 
@@ -235,7 +234,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                               "dvb%d.%s%d", adap->num, dnames[type], id);
        if (IS_ERR(clsdev)) {
                printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
-                      __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+                      __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
                return PTR_ERR(clsdev);
        }
 
@@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
+static int dvbdev_check_free_adapter_num(int num)
+{
+       struct list_head *entry;
+       list_for_each(entry, &dvb_adapter_list) {
+               struct dvb_adapter *adap;
+               adap = list_entry(entry, struct dvb_adapter, list_head);
+               if (adap->num == num)
+                       return 0;
+       }
+       return 1;
+}
 
 static int dvbdev_get_free_adapter_num (void)
 {
        int num = 0;
 
        while (num < DVB_MAX_ADAPTERS) {
-               struct dvb_adapter *adap;
-               list_for_each_entry(adap, &dvb_adapter_list, list_head)
-                       if (adap->num == num)
-                               goto skip;
-               return num;
-skip:
+               if (dvbdev_check_free_adapter_num(num))
+                       return num;
                num++;
        }
 
@@ -281,13 +287,28 @@ skip:
 }
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+                        struct module *module, struct device *device,
+                        short *adapter_nums)
 {
-       int num;
+       int i, num;
 
        mutex_lock(&dvbdev_register_lock);
 
-       if ((num = dvbdev_get_free_adapter_num ()) < 0) {
+       for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
+               num = adapter_nums[i];
+               if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
+               /* use the one the driver asked for */
+                       if (dvbdev_check_free_adapter_num(num))
+                               break;
+               } else {
+                       num = dvbdev_get_free_adapter_num();
+                       break;
+               }
+               num = -1;
+       }
+
+       if (num < 0) {
                mutex_unlock(&dvbdev_register_lock);
                return -ENFILE;
        }
index 6dff10ebf47052a1f92872e7a95541f56e845646..5f9a737c6de194065d3e5f7e4de06e0407d8c322 100644 (file)
 
 #define DVB_MAJOR 212
 
+#define DVB_MAX_ADAPTERS 8
+
+#define DVB_UNSET (-1)
+
 #define DVB_DEVICE_VIDEO      0
 #define DVB_DEVICE_AUDIO      1
 #define DVB_DEVICE_SEC        2
 #define DVB_DEVICE_NET        7
 #define DVB_DEVICE_OSD        8
 
+#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
+       static short adapter_nr[] = \
+               {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
+       module_param_array(adapter_nr, short, NULL, 0444); \
+       MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
 
 struct dvb_adapter {
        int num;
@@ -78,7 +87,9 @@ struct dvb_device {
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
+extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+                               struct module *module, struct device *device,
+                               short *adapter_nums);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
index d73934dd4c573790790c9cd885db3ef7063f02f7..3c8493d2026dd329a9e20c1c6faaf2d9581b94b3 100644 (file)
@@ -105,6 +105,7 @@ config DVB_USB_CXUSB
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
index a6c5f19f680d6dd38452a0f5356885bfa082994b..dc8c8784caa8a8c46e36886acdcbff6e8f3eeb1e 100644 (file)
@@ -18,6 +18,9 @@
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...)   dprintk(debug,0x01,args)
 
 static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
@@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties;
 static int a800_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &a800_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index e7f76f515b4f6bbe293832596daf20c78dc0d0b4..cfe71feefcad27a8e64598316a366bda99ae8985 100644 (file)
@@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0;
 module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
 MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* remote control decoder */
 int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
                  int *state);
@@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties;
 static int af9005_usb_probe(struct usb_interface *intf,
                            const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
+       return dvb_usb_device_init(intf, &af9005_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id af9005_usb_table[] = {
index f3ff8131469607422e2599b88492521bac9e3f78..2ccb90fa60c85917cd9604443cb13e5169e61f5f 100644 (file)
@@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug;
 module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
                          u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf,
        if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
                return -ENODEV;
 
-       if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
+       ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
+                                 adapter_nr);
+       if (ret == 0) {
                alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
 
                if (alt == NULL) {
index c58365005ac1cb32e0f7739918f6e3b3f8a37a97..720fcd1c3c1d75caad387932f9bc56329c42ff47 100644 (file)
@@ -23,6 +23,8 @@
  *
  * see Documentation/dvb/README.dvb-usb for more information
  */
+#include <media/tuner.h>
+
 #include "cxusb.h"
 
 #include "cx22702.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
 #include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
+#include "tuner-simple.h"
 
 /* debug */
 static int dvb_usb_cxusb_debug;
 module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
 #define deb_i2c(args...)    if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
                                dprintk(dvb_usb_cxusb_debug,0x01,args)
@@ -450,8 +455,9 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
-                  DVB_PLL_FMD1216ME);
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->dev->i2c_adap, 0x61,
+                  TUNER_PHILIPS_FMD1216ME_MK3);
        return 0;
 }
 
@@ -477,8 +483,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
-                  DVB_PLL_LG_TDVS_H06XF);
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
        return 0;
 }
 
@@ -488,14 +494,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
 
        switch (command) {
        case XC2028_TUNER_RESET:
-               deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+               deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
                cxusb_bluebird_gpio_pulse(d, 0x01, 1);
                break;
        case XC2028_RESET_CLK:
-               deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+               deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
                break;
        default:
-               deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
+               deb_info("%s: unknown command %d, arg %d\n", __func__,
                         command, arg);
                return -EINVAL;
        }
@@ -509,13 +515,12 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
        struct xc2028_config      cfg = {
                .i2c_adap  = &adap->dev->i2c_adap,
                .i2c_addr  = 0x61,
-               .video_dev = adap->dev,
                .callback  = dvico_bluebird_xc2028_callback,
        };
        static struct xc2028_ctrl ctl = {
                .fname       = "xc3028-dvico-au-01.fw",
                .max_len     = 64,
-               .scode_table = ZARLINK456,
+               .scode_table = XC3028_FE_ZARLINK456,
        };
 
        fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
@@ -720,16 +725,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
 static int cxusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
+       if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf,
+                               &cxusb_bluebird_nano2_needsfirmware_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
-       }
 
        return -EINVAL;
 }
index 4a903ea958965d5bc7cbadbd96f2282e89dedf34..66d4dc6ba46fe8a78a9d597f3d45bdb6e6c5cf01 100644 (file)
@@ -37,6 +37,7 @@ struct dib0700_state {
        u8 channel_state;
        u16 mt2060_if1[2];
        u8 rc_toggle;
+       u8 rc_counter;
        u8 is_dib7000pc;
 };
 
@@ -44,12 +45,15 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8
 extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
 extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
 extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
+extern int dib0700_rc_setup(struct dvb_usb_device *d);
 extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
                        struct dvb_usb_device_description **desc, int *cold);
 
 extern int dib0700_device_count;
+extern int dvb_usb_dib0700_ir_proto;
 extern struct dvb_usb_device_properties dib0700_devices[];
 extern struct usb_device_id dib0700_usb_id_table[];
+
 #endif
index c9857d5c69829e68bbc9e82af68026ebc4d4288c..595a04696c87af2590588bf87013a44b8e44aa7c 100644 (file)
@@ -13,10 +13,12 @@ int dvb_usb_dib0700_debug;
 module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
 
-static int dvb_usb_dib0700_ir_proto = 1;
+int dvb_usb_dib0700_ir_proto = 1;
 module_param(dvb_usb_dib0700_ir_proto, int, 0644);
 MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* expecting rx buffer: request data[0] data[1] ... data[2] */
 static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
 {
@@ -261,7 +263,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return dib0700_ctrl_wr(adap->dev, b, 4);
 }
 
-static int dib0700_rc_setup(struct dvb_usb_device *d)
+int dib0700_rc_setup(struct dvb_usb_device *d)
 {
        u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
        int i = dib0700_ctrl_wr(d, rc_setup, 3);
@@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf,
        struct dvb_usb_device *dev;
 
        for (i = 0; i < dib0700_device_count; i++)
-               if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
+               if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
+                                       &dev, adapter_nr) == 0)
                {
                        dib0700_rc_setup(dev);
                        return 0;
index e7093826e975896f31153621f08edf7aef219bf7..6477fc66cc2381da08ff3637673e04042388470b 100644 (file)
@@ -13,6 +13,7 @@
 #include "dib7000p.h"
 #include "mt2060.h"
 #include "mt2266.h"
+#include "tuner-xc2028.h"
 #include "dib0070.h"
 
 static int force_lna_activation;
@@ -297,10 +298,156 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
                &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
 }
 
+/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
+struct dibx000_agc_config xc3028_agc_config = {
+       BAND_VHF | BAND_UHF,       /* band_caps */
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+        * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+        * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+       (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+       (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+       712,    /* inv_gain */
+       21,     /* time_stabiliz */
+
+       0,      /* alpha_level */
+       118,    /* thlock */
+
+       0,      /* wbd_inv */
+       2867,   /* wbd_ref */
+       0,      /* wbd_sel */
+       2,      /* wbd_alpha */
+
+       0,      /* agc1_max */
+       0,      /* agc1_min */
+       39718,  /* agc2_max */
+       9930,   /* agc2_min */
+       0,      /* agc1_pt1 */
+       0,      /* agc1_pt2 */
+       0,      /* agc1_pt3 */
+       0,      /* agc1_slope1 */
+       0,      /* agc1_slope2 */
+       0,      /* agc2_pt1 */
+       128,    /* agc2_pt2 */
+       29,     /* agc2_slope1 */
+       29,     /* agc2_slope2 */
+
+       17,     /* alpha_mant */
+       27,     /* alpha_exp */
+       23,     /* beta_mant */
+       51,     /* beta_exp */
+
+       1,      /* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
+struct dibx000_bandwidth_config xc3028_bw_config = {
+       60000, 30000, /* internal, sampling */
+       1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
+       0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
+                         modulo */
+       (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+       (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+       20452225, /* timf */
+       30000000, /* xtal_hz */
+};
+
+static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
+       .output_mpeg2_in_188_bytes = 1,
+       .tuner_is_baseband = 1,
+
+       .agc_config_count = 1,
+       .agc = &xc3028_agc_config,
+       .bw  = &xc3028_bw_config,
+
+       .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+};
+
+static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
+{
+       struct dvb_usb_adapter *adap = ptr;
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               /* Send the tuner in then out of reset */
+               dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
+               dib7000p_set_gpio(adap->fe, 8, 0, 1);
+               break;
+       case XC2028_RESET_CLK:
+               break;
+       default:
+               err("%s: unknown command %d, arg %d\n", __func__,
+                       command, arg);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
+       .fname = XC2028_DEFAULT_FIRMWARE,
+       .max_len = 64,
+       .demod = XC3028_FE_DIBCOM52,
+};
+
+static struct xc2028_config stk7700ph_xc3028_config = {
+       .i2c_addr = 0x61,
+       .callback = stk7700ph_xc3028_callback,
+       .ctrl = &stk7700ph_xc3028_ctrl,
+};
+
+static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
+
+       if (desc->idVendor  == USB_VID_PINNACLE &&
+           desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+       else
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       msleep(10);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(20);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+       msleep(10);
+
+       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+               &stk7700ph_dib7700_xc3028_config);
+
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+               &stk7700ph_dib7700_xc3028_config);
+
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct i2c_adapter *tun_i2c;
+
+       tun_i2c = dib7000p_get_i2c_master(adap->fe,
+               DIBX000_I2C_INTERFACE_TUNER, 1);
+
+       stk7700ph_xc3028_config.i2c_adap = tun_i2c;
+       stk7700ph_xc3028_config.video_dev = adap;
+
+       return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+               == NULL ? -ENODEV : 0;
+}
+
 #define DEFAULT_RC_INTERVAL 150
 
 static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
 
+/* Number of keypresses to ignore before start repeating */
+#define RC_REPEAT_DELAY 2
+
 static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        u8 key[4];
@@ -314,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                err("RC Query Failed");
                return -1;
        }
+
+       /* losing half of KEY_0 events from Philipps rc5 remotes.. */
        if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
-       if (key[3-1]!=st->rc_toggle) {
+
+       /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
+
+       dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
+
+       switch (dvb_usb_dib0700_ir_proto) {
+       case 0: {
+               /* NEC protocol sends repeat code as 0 0 0 FF */
+               if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
+                   (key[3] == 0xFF)) {
+                       st->rc_counter++;
+                       if (st->rc_counter > RC_REPEAT_DELAY) {
+                               *event = d->last_event;
+                               *state = REMOTE_KEY_PRESSED;
+                               st->rc_counter = RC_REPEAT_DELAY;
+                       }
+                       return 0;
+               }
                for (i=0;i<d->props.rc_key_map_size; i++) {
                        if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
+                               st->rc_counter = 0;
+                               *event = keymap[i].event;
+                               *state = REMOTE_KEY_PRESSED;
+                               d->last_event = keymap[i].event;
+                               return 0;
+                       }
+               }
+               break;
+       }
+       default: {
+               /* RC-5 protocol changes toggle bit on new keypress */
+               for (i = 0; i < d->props.rc_key_map_size; i++) {
+                       if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
+                               if (d->last_event == keymap[i].event &&
+                                       key[3-1] == st->rc_toggle) {
+                                       st->rc_counter++;
+                                       /* prevents unwanted double hits */
+                                       if (st->rc_counter > RC_REPEAT_DELAY) {
+                                               *event = d->last_event;
+                                               *state = REMOTE_KEY_PRESSED;
+                                               st->rc_counter = RC_REPEAT_DELAY;
+                                       }
+
+                                       return 0;
+                               }
+                               st->rc_counter = 0;
                                *event = keymap[i].event;
                                *state = REMOTE_KEY_PRESSED;
-                               st->rc_toggle=key[3-1];
+                               st->rc_toggle = key[3-1];
+                               d->last_event = keymap[i].event;
                                return 0;
                        }
                }
-               err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
+               break;
        }
+       }
+       err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
+       d->last_event = 0;
        return 0;
 }
 
@@ -794,6 +990,10 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
 /* STK7070P */
 static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
 {
+       if (adap->dev->udev->descriptor.idVendor  == USB_VID_PINNACLE &&
+       adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+       else
        dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -808,9 +1008,11 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
        msleep(10);
        dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
+       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+               &dib7070p_dib7000p_config);
 
-       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+               &dib7070p_dib7000p_config);
        return adap->fe == NULL ? -ENODEV : 0;
 }
 
@@ -878,34 +1080,43 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
 /* DVB-USB and USB stuff follows */
 struct usb_device_id dib0700_usb_id_table[] = {
 /* 0 */        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
-
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
 /* 5 */        { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
-               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
-               { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
-               { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+       { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
+       { USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
+       { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
 /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
-               { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
+       { USB_DEVICE(USB_VID_TERRATEC,
+                       USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
 /* 15 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070P) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
-               { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
-               { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
-               { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
+       { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
+       { USB_DEVICE(USB_VID_PINNACLE,
+                       USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
+       { USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
 /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
-               { USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
-               { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
-               { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
-               { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
-/* 25 */       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
-               { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
-               { 0 }           /* Terminating entry */
+       { USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
+       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
+       { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
+       { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
+/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_USB_XE) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_EXPRESSCARD_320CX) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV72E) },
+/* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) },
+       { USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_EC372S) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
+       { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_XXS) },
+       { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
+       { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
 
@@ -969,7 +1180,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { NULL },
                        },
                        {   "Leadtek Winfast DTV Dongle (STK7700P based)",
-                               { &dib0700_usb_id_table[8], NULL },
+                               { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] },
                                { NULL },
                        },
                        {   "AVerMedia AVerTV DVB-T Express",
@@ -1069,12 +1280,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 1,
+               .num_device_descs = 2,
                .devices = {
                        {   "ASUS My Cinema U3000 Mini DVBT Tuner",
                                { &dib0700_usb_id_table[23], NULL },
                                { NULL },
                        },
+                       {   "Yuan EC372S",
+                               { &dib0700_usb_id_table[31], NULL },
+                               { NULL },
+                       }
                }
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
@@ -1090,7 +1305,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 6,
+               .num_device_descs = 9,
                .devices = {
                        {   "DiBcom STK7070P reference design",
                                { &dib0700_usb_id_table[15], NULL },
@@ -1116,6 +1331,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[26], NULL },
                                { NULL },
                        },
+                       {   "Pinnacle PCTV 72e",
+                               { &dib0700_usb_id_table[29], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle PCTV 73e",
+                               { &dib0700_usb_id_table[30], NULL },
+                               { NULL },
+                       },
+                       {   "Terratec Cinergy T USB XXS",
+                               { &dib0700_usb_id_table[33], NULL },
+                               { NULL },
+                       },
                },
 
                .rc_interval      = DEFAULT_RC_INTERVAL,
@@ -1155,6 +1382,40 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { NULL },
                        }
                }
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .frontend_attach  = stk7700ph_frontend_attach,
+                               .tuner_attach     = stk7700ph_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+                               .size_of_priv = sizeof(struct
+                                               dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 3,
+               .devices = {
+                       {   "Terratec Cinergy HT USB XE",
+                               { &dib0700_usb_id_table[27], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle Expresscard 320cx",
+                               { &dib0700_usb_id_table[28], NULL },
+                               { NULL },
+                       },
+                       {   "Terratec Cinergy HT Express",
+                               { &dib0700_usb_id_table[32], NULL },
+                               { NULL },
+                       },
+               },
+               .rc_interval      = DEFAULT_RC_INTERVAL,
+               .rc_key_map       = dib0700_rc_keys,
+               .rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+               .rc_query         = dib0700_rc_query
        },
 };
 
index 043cadae08594f62ed1dead95e77439e728a3a2d..eeef50bff4f9b39c41e984ffd52a76ccb2720ddf 100644 (file)
@@ -14,6 +14,8 @@
  */
 #include "dibusb.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct dvb_usb_adapter *adap = fe->dvb->priv;
@@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties;
 static int dibusb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
 
        return -EINVAL;
index e7ea3e753d6da2eb287af30cb9b245214352b20b..059cec95531826aa8128bc3bcdc6e57e371ee6e7 100644 (file)
  */
 #include "dibusb.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* USB Driver stuff */
 static struct dvb_usb_device_properties dibusb_mc_properties;
 
 static int dibusb_mc_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
+                                  NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index 3acbda4aa27e1e550cb548e4f2972c050c8d4ada..b545cf3eab2e5c0a63ac1f48ca67fca3cf8eae21 100644 (file)
@@ -20,6 +20,9 @@
 static int dvb_usb_digitv_debug;
 module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
 
 static int digitv_ctrl_msg(struct dvb_usb_device *d,
@@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
        struct dvb_usb_device *d;
-       int ret;
-       if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+       int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
+                                     adapter_nr);
+       if (ret == 0) {
                u8 b[4] = { 0 };
 
                if (d != NULL) { /* do that only when the firmware is loaded */
index d86cf9bee91c23fdd8ec0b528994b51b95cd6f7b..81a6cbf601603a6e8b2313921291350b131bd1ae 100644 (file)
@@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug;
 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        u8 b = SET_INIT;
@@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
 static int dtt200u_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
 
        return -ENODEV;
index 35ab68f6dcf6346e5748e775c95a722c478295e5..6b7b2a89242e797d9bbe0c959ddef57515a25a8f 100644 (file)
@@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
 extern int dvb_usb_i2c_init(struct dvb_usb_device *);
 extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
 
-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
+                                   short *adapter_nums);
 extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
 extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
index 4561a672da924c70ab9ba121c056b4591b1f55e4..ce8cd0c5d83120b173ad5fa4950d1f43a8c0a585 100644 (file)
@@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
        return dvb_usb_ctrl_feed(dvbdmxfeed,0);
 }
 
-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
+int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
 {
-       int ret;
+       int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+                                      adap->dev->owner, &adap->dev->udev->dev,
+                                      adapter_nums);
 
-       if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
-                       adap->dev->owner, &adap->dev->udev->dev)) < 0) {
+       if (ret < 0) {
                deb_info("dvb_register_adapter failed: error %d", ret);
                goto err;
        }
index aa4844ef875e02798c6f761423a0f33d9aeffd79..34245d1b7dd92a151233de0e266466e1df4b06ae 100644 (file)
 #define USB_VID_MSI                            0x0db0
 #define USB_VID_OPERA1                         0x695c
 #define USB_VID_PINNACLE                       0x2304
+#define USB_VID_TECHNOTREND                    0x0b48
 #define USB_VID_TERRATEC                       0x0ccd
 #define USB_VID_VISIONPLUS                     0x13d3
 #define USB_VID_TWINHAN                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC              0x05d8
 #define USB_VID_UNIWILL                                0x1584
 #define USB_VID_WIDEVIEW                       0x14aa
-/* dom : pour gigabyte u7000 */
 #define USB_VID_GIGABYTE                       0x1044
+#define USB_VID_YUAN                           0x1164
 
 
 /* Product IDs */
 #define USB_PID_AVERMEDIA_EXPRESS                      0xb568
 #define USB_PID_AVERMEDIA_VOLAR                                0xa807
 #define USB_PID_AVERMEDIA_VOLAR_2                      0xb808
+#define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
+#define USB_PID_TERRATEC_CINERGY_HT_USB_XE             0x0058
+#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS            0x0060
+#define USB_PID_TERRATEC_CINERGY_T_XXS                 0x0078
+#define USB_PID_PINNACLE_EXPRESSCARD_320CX             0x022e
 #define USB_PID_PINNACLE_PCTV2000E                     0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH              0x0228
 #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T     0x0229
+#define USB_PID_PINNACLE_PCTV72E                       0x0236
+#define USB_PID_PINNACLE_PCTV73E                       0x0237
 #define USB_PID_PCTV_200E                              0x020e
 #define USB_PID_PCTV_400E                              0x020f
 #define USB_PID_PCTV_450E                              0x0222
 #define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2          0x6f01
 #define USB_PID_GENPIX_8PSK_REV_1_COLD                 0x0200
 #define USB_PID_GENPIX_8PSK_REV_1_WARM                 0x0201
 #define USB_PID_GENPIX_8PSK_REV_2                      0x0202
 #define USB_PID_OPERA1_WARM                            0x3829
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD           0x0514
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM           0x0513
-/* dom pour gigabyte u7000 */
 #define USB_PID_GIGABYTE_U7000                         0x7001
 #define USB_PID_ASUS_U3000                             0x171f
 #define USB_PID_ASUS_U3100                             0x173f
+#define USB_PID_YUAN_EC372S                            0x1edc
 
 #endif
index cdd717c3fe45ac79c099a49397d529cf0ffdda5c..e331db8c77b210125c72f4cb475e4c71c9ca8798 100644 (file)
@@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage;
 module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
 MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
 
-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
        struct dvb_usb_adapter *adap;
        int ret,n;
@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d)
                }
 
                if ((ret = dvb_usb_adapter_stream_init(adap)) ||
-                       (ret = dvb_usb_adapter_dvb_init(adap)) ||
+                       (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
                        (ret = dvb_usb_adapter_frontend_init(adap))) {
                        return ret;
                }
@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
        return 0;
 }
 
-static int dvb_usb_init(struct dvb_usb_device *d)
+static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
 {
        int ret = 0;
 
@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
        dvb_usb_device_power_ctrl(d, 1);
 
        if ((ret = dvb_usb_i2c_init(d)) ||
-               (ret = dvb_usb_adapter_init(d))) {
+               (ret = dvb_usb_adapter_init(d, adapter_nums))) {
                dvb_usb_exit(d);
                return ret;
        }
@@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
 /*
  * USB
  */
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
-               *props, struct module *owner,struct dvb_usb_device **du)
+int dvb_usb_device_init(struct usb_interface *intf,
+                       struct dvb_usb_device_properties *props,
+                       struct module *owner, struct dvb_usb_device **du,
+                       short *adapter_nums)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct dvb_usb_device *d = NULL;
@@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper
        if (du != NULL)
                *du = d;
 
-       ret = dvb_usb_init(d);
+       ret = dvb_usb_init(d, adapter_nums);
 
        if (ret == 0)
                info("%s successfully initialized and connected.",desc->name);
index d1b3c7b81fffebad0da13a96406903d276db1d01..b1de0f7e26e8dce984c41bf6388ed6d2e932bd5d 100644 (file)
@@ -372,7 +372,10 @@ struct dvb_usb_device {
        void *priv;
 };
 
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
+extern int dvb_usb_device_init(struct usb_interface *,
+                              struct dvb_usb_device_properties *,
+                              struct module *, struct dvb_usb_device **,
+                              short *adapter_nums);
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
index 6b99d9f4d5b35846892f023998d903aafdc8caa5..0a8ac64a4e33a6a345cd6eea538b7397a33c6536 100644 (file)
@@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug;
 module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
                         u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf,
        if (intf->num_altsetting < 2)
                return -ENODEV;
 
-       if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
+       ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
+                                 adapter_nr);
+       if (ret == 0) {
                alt = usb_altnum_to_altsetting(intf, 0);
 
                if (alt == NULL) {
index e37142d9271a83aa0f1b3e3575e21dc3c5a8a6f3..262a858c30684e28e0798034e776ed9138f3f255 100644 (file)
@@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
 {
        struct gp8psk_fe_state *st = fe->demodulator_priv;
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
                        m->msg, m->msg_len)) {
@@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
        struct gp8psk_fe_state *st = fe->demodulator_priv;
        u8 cmd;
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        /* These commands are certainly wrong */
        cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
index 83e8535014c6d092fc08f5c91e0963f31408dca2..9a942afaf0af8d1a3c16cf9e5681656d3c1eca72 100644 (file)
@@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug;
 module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
 {
        int ret = 0,try = 0;
@@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
 {
        int ret;
        struct usb_device *udev = interface_to_usbdev(intf);
-       ret =  dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+       ret = dvb_usb_device_init(intf, &gp8psk_properties,
+                                 THIS_MODULE, NULL, adapter_nr);
        if (ret == 0) {
                info("found Genpix USB device pID = %x (hex)",
                        le16_to_cpu(udev->descriptor.idProduct));
index a956bc503a4c7aa6480e06c21a6900c6328cee60..a12e6f784fdae92aade0f2b08040f93948206155 100644 (file)
@@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug;
 module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
 
 static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
@@ -477,7 +479,7 @@ static struct qt1010_config m920x_qt1010_config = {
 /* Callbacks for DVB USB */
 static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(mt352_attach,
                                   &m920x_mt352_config,
@@ -489,7 +491,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_08_config,
@@ -501,7 +503,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if ((adap->fe = dvb_attach(tda10046_attach,
                                   &m920x_tda10046_0b_config,
@@ -513,7 +515,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
                return -ENODEV;
@@ -523,7 +525,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -533,7 +535,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
 
 static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb("%s\n",__FUNCTION__);
+       deb("%s\n",__func__);
 
        if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
                return -ENODEV;
@@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf,
                 * multi-tuner device
                 */
 
-               if ((ret = dvb_usb_device_init(intf, &megasky_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &megasky_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = megasky_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* No remote control, so no rc_init_seq */
                        goto found;
                }
 
                /* This configures both tuners on the TV Walker Twin */
-               if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        rc_init_seq = tvwalkertwin_rc_init;
                        goto found;
                }
 
-               if ((ret = dvb_usb_device_init(intf, &dposh_properties,
-                                              THIS_MODULE, &d)) == 0) {
+               ret = dvb_usb_device_init(intf, &dposh_properties,
+                                         THIS_MODULE, &d, adapter_nr);
+               if (ret == 0) {
                        /* Remote controller not supported yet. */
                        goto found;
                }
index badc468170ea615aff5a0eaa2332cd6559db4f09..07fb843c7c2b22d35b4a977dd405e2b6d5e97ab7 100644 (file)
@@ -15,6 +15,8 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_rc(args...) dprintk(debug,0x01,args)
 #define deb_ee(args...) dprintk(debug,0x02,args)
 
@@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties;
 static int nova_t_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &nova_t_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 /* do not change the order of the ID table */
index 302cc67407c397e17091bc729c078e9d63f54031..7e32d11f32b0fd6e4ddc41714d7dd3242bacc819 100644 (file)
@@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug,
                 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
                 DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+
 static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
                            u8 * data, u16 len, int flags)
 {
@@ -243,7 +246,7 @@ static struct stv0299_config opera1_stv0299_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_0,
+       .lock_output = STV0299_LOCKOUTPUT_0,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .inittab = opera1_inittab,
        .set_symbol_rate = opera1_stv0299_set_symbol_rate,
@@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf,
                return -EINVAL;
        }
 
-       if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
+       if (0 != dvb_usb_device_init(intf, &opera1_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return -EINVAL;
        return 0;
 }
index 3b9da9c25c6e8d15dc48925b8cd399533453fc6e..20ca9d9ee99b23aedb60d3ecf3e892c5d9ae71a5 100644 (file)
@@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug;
 module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct ttusb2_state {
        u8 id;
 };
@@ -145,6 +147,7 @@ static struct tda10086_config tda10086_config = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 1,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
 static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
 
 /* DVB USB Driver stuff */
 static struct dvb_usb_device_properties ttusb2_properties;
+static struct dvb_usb_device_properties ttusb2_properties_s2400;
 
 static int ttusb2_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
+       if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
+                                    THIS_MODULE, NULL, adapter_nr))
+               return 0;
+       return -ENODEV;
 }
 
 static struct usb_device_id ttusb2_table [] = {
-               { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
-               { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
-               {}              /* Terminating entry */
+       { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+       { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
+       { USB_DEVICE(USB_VID_TECHNOTREND,
+               USB_PID_TECHNOTREND_CONNECT_S2400) },
+       {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, ttusb2_table);
 
@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
        }
 };
 
+static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-tt-s2400-01.fw",
+
+       .size_of_priv = sizeof(struct ttusb2_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = NULL,
+
+                       .frontend_attach  = ttusb2_frontend_attach,
+                       .tuner_attach     = ttusb2_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_ISOC,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .isoc = {
+                                               .framesperurb = 4,
+                                               .framesize = 940,
+                                               .interval = 1,
+                                       }
+                               }
+                       }
+               }
+       },
+
+       .power_ctrl       = ttusb2_power_ctrl,
+       .identify_state   = ttusb2_identify_state,
+
+       .i2c_algo         = &ttusb2_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "Technotrend TT-connect S-2400",
+                       { &ttusb2_table[2], NULL },
+                       { NULL },
+               },
+       }
+};
+
 static struct usb_driver ttusb2_driver = {
        .name           = "dvb_usb_ttusb2",
        .probe          = ttusb2_probe,
index 0dcab3d4e2362bcfd5f1862a236aa56f4b94b920..9e7653bb3b660bc4c44985db551cf94e0f65ee5e 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "mt352.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static int umt_mt352_demod_init(struct dvb_frontend *fe)
 {
        static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
@@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties;
 static int umt_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
+       if (0 == dvb_usb_device_init(intf, &umt_properties,
+                                    THIS_MODULE, NULL, adapter_nr))
                return 0;
        return -EINVAL;
 }
index c3fdc7cd094e33f41c4e2c34f4ec7b565233d2e6..ccc7e445266450dc41efd1313396b53c762db46d 100644 (file)
@@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        vp702x_fe_refresh_state(st);
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (st->lock == 0)
                *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
@@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
 
 static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        tune->min_delay_ms = 2000;
        return 0;
 }
@@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
 static int vp702x_fe_init(struct dvb_frontend *fe)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
        return 0;
 }
 
 static int vp702x_fe_sleep(struct dvb_frontend *fe)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
 static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
        u8 cmd[8],ibuf[10];
        memset(cmd,0,8);
 
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        if (m->msg_len > 4)
                return -EINVAL;
@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 
 static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
        return 0;
 }
 
@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        u8 ibuf[10];
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        st->tone_mode = tone;
 
@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
 {
        struct vp702x_fe_state *st = fe->demodulator_priv;
        u8 ibuf[10];
-       deb_fe("%s\n",__FUNCTION__);
+       deb_fe("%s\n",__func__);
 
        st->voltage = voltage;
 
index e553c139ac44947abbc4ad010564ec4ec8bdcb6d..986fff9a5ba81580c6a40bcbfb2bd13100b0dddb 100644 (file)
@@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug;
 module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct vp702x_state {
        int pid_filter_count;
        int pid_filter_can_bypass;
@@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties;
 static int vp702x_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &vp702x_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id vp702x_usb_table [] = {
index c172babf59bbf5d850c41dcb2eacd083887ce4ce..acb345504e0da0cbd8d3c2d3541a1a5a092a6def 100644 (file)
@@ -18,6 +18,9 @@
 static int dvb_usb_vp7045_debug;
 module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
 #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
 #define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
@@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
+       return dvb_usb_device_init(intf, &vp7045_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
index 9ad86ce4a4e5b783e0d8627e2b30b0f816ef8245..68fab616f55dfa483d62f3d69cb3ad4c6f4ac5ad 100644 (file)
@@ -188,6 +188,14 @@ config DVB_DIB7000P
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
 
+config DVB_TDA10048
+       tristate "Philips TDA10048HN based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       select FW_LOADER
+       help
+         A DVB-T tuner module. Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
        depends on DVB_CORE
 
@@ -291,6 +299,14 @@ config DVB_S5H1409
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+config DVB_AU8522
+       tristate "Auvitek AU8522 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 comment "Tuners/PLL support"
        depends on DVB_CORE
 
@@ -369,6 +385,11 @@ config DVB_TUNER_XC5000
          This device is only used inside a SiP called togther with a
          demodulator for now.
 
+config DVB_TUNER_ITD1000
+       tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+
 comment "Miscellaneous devices"
        depends on DVB_CORE
 
@@ -379,6 +400,13 @@ config DVB_LNBP21
        help
          An SEC control chip.
 
+config DVB_ISL6405
+       tristate "ISL6405 SEC controller"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         An SEC control chip.
+
 config DVB_ISL6421
        tristate "ISL6421 SEC controller"
        depends on DVB_CORE && I2C
index 16bd107ebd32d83a2c64da419a367f0351e37820..2f873fc0f6498e2aa52dfdcee0cb7b1f44d9c2c1 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
@@ -51,3 +52,6 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
 obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
+obj-$(CONFIG_DVB_AU8522) += au8522.o
+obj-$(CONFIG_DVB_TDA10048) += tda10048.o
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
new file mode 100644 (file)
index 0000000..084a280
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "au8522.h"
+
+struct au8522_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct au8522_config *config;
+
+       struct dvb_frontend frontend;
+
+       u32 current_frequency;
+       fe_modulation_t current_modulation;
+
+};
+
+static int debug;
+
+#define dprintk(arg...) do {           \
+       if (debug)                      \
+                printk(arg);           \
+       } while (0)
+
+/* 16 bit registers, 8 bit values */
+static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+       int ret;
+       u8 buf [] = { reg >> 8, reg & 0xff, data };
+
+       struct i2c_msg msg = { .addr = state->config->demod_address,
+                              .flags = 0, .buf = buf, .len = 3 };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+                      "ret == %i)\n", __func__, reg, data, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+       int ret;
+       u8 b0 [] = { reg >> 8, reg & 0xff };
+       u8 b1 [] = { 0 };
+
+       struct i2c_msg msg [] = {
+               { .addr = state->config->demod_address, .flags = 0,
+                 .buf = b0, .len = 2 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD,
+                 .buf = b1, .len = 1 } };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                      __func__, ret);
+       return b1[0];
+}
+
+static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return au8522_writereg(state, 0x106, 1);
+       else
+               return au8522_writereg(state, 0x106, 0);
+}
+
+struct mse2snr_tab {
+       u16 val;
+       u16 data;
+};
+
+/* VSB SNR lookup table */
+static struct mse2snr_tab vsb_mse2snr_tab[] = {
+       {   0, 270 },
+       {   2, 250 },
+       {   3, 240 },
+       {   5, 230 },
+       {   7, 220 },
+       {   9, 210 },
+       {  12, 200 },
+       {  13, 195 },
+       {  15, 190 },
+       {  17, 185 },
+       {  19, 180 },
+       {  21, 175 },
+       {  24, 170 },
+       {  27, 165 },
+       {  31, 160 },
+       {  32, 158 },
+       {  33, 156 },
+       {  36, 152 },
+       {  37, 150 },
+       {  39, 148 },
+       {  40, 146 },
+       {  41, 144 },
+       {  43, 142 },
+       {  44, 140 },
+       {  48, 135 },
+       {  50, 130 },
+       {  43, 142 },
+       {  53, 125 },
+       {  56, 120 },
+       { 256, 115 },
+};
+
+/* QAM64 SNR lookup table */
+static struct mse2snr_tab qam64_mse2snr_tab[] = {
+       {  15,   0 },
+       {  16, 290 },
+       {  17, 288 },
+       {  18, 286 },
+       {  19, 284 },
+       {  20, 282 },
+       {  21, 281 },
+       {  22, 279 },
+       {  23, 277 },
+       {  24, 275 },
+       {  25, 273 },
+       {  26, 271 },
+       {  27, 269 },
+       {  28, 268 },
+       {  29, 266 },
+       {  30, 264 },
+       {  31, 262 },
+       {  32, 260 },
+       {  33, 259 },
+       {  34, 258 },
+       {  35, 256 },
+       {  36, 255 },
+       {  37, 254 },
+       {  38, 252 },
+       {  39, 251 },
+       {  40, 250 },
+       {  41, 249 },
+       {  42, 248 },
+       {  43, 246 },
+       {  44, 245 },
+       {  45, 244 },
+       {  46, 242 },
+       {  47, 241 },
+       {  48, 240 },
+       {  50, 239 },
+       {  51, 238 },
+       {  53, 237 },
+       {  54, 236 },
+       {  56, 235 },
+       {  57, 234 },
+       {  59, 233 },
+       {  60, 232 },
+       {  62, 231 },
+       {  63, 230 },
+       {  65, 229 },
+       {  67, 228 },
+       {  68, 227 },
+       {  70, 226 },
+       {  71, 225 },
+       {  73, 224 },
+       {  74, 223 },
+       {  76, 222 },
+       {  78, 221 },
+       {  80, 220 },
+       {  82, 219 },
+       {  85, 218 },
+       {  88, 217 },
+       {  90, 216 },
+       {  92, 215 },
+       {  93, 214 },
+       {  94, 212 },
+       {  95, 211 },
+       {  97, 210 },
+       {  99, 209 },
+       { 101, 208 },
+       { 102, 207 },
+       { 104, 206 },
+       { 107, 205 },
+       { 111, 204 },
+       { 114, 203 },
+       { 118, 202 },
+       { 122, 201 },
+       { 125, 200 },
+       { 128, 199 },
+       { 130, 198 },
+       { 132, 197 },
+       { 256, 190 },
+};
+
+/* QAM256 SNR lookup table */
+static struct mse2snr_tab qam256_mse2snr_tab[] = {
+       {  16,   0 },
+       {  17, 400 },
+       {  18, 398 },
+       {  19, 396 },
+       {  20, 394 },
+       {  21, 392 },
+       {  22, 390 },
+       {  23, 388 },
+       {  24, 386 },
+       {  25, 384 },
+       {  26, 382 },
+       {  27, 380 },
+       {  28, 379 },
+       {  29, 378 },
+       {  30, 377 },
+       {  31, 376 },
+       {  32, 375 },
+       {  33, 374 },
+       {  34, 373 },
+       {  35, 372 },
+       {  36, 371 },
+       {  37, 370 },
+       {  38, 362 },
+       {  39, 354 },
+       {  40, 346 },
+       {  41, 338 },
+       {  42, 330 },
+       {  43, 328 },
+       {  44, 326 },
+       {  45, 324 },
+       {  46, 322 },
+       {  47, 320 },
+       {  48, 319 },
+       {  49, 318 },
+       {  50, 317 },
+       {  51, 316 },
+       {  52, 315 },
+       {  53, 314 },
+       {  54, 313 },
+       {  55, 312 },
+       {  56, 311 },
+       {  57, 310 },
+       {  58, 308 },
+       {  59, 306 },
+       {  60, 304 },
+       {  61, 302 },
+       {  62, 300 },
+       {  63, 298 },
+       {  65, 295 },
+       {  68, 294 },
+       {  70, 293 },
+       {  73, 292 },
+       {  76, 291 },
+       {  78, 290 },
+       {  79, 289 },
+       {  81, 288 },
+       {  82, 287 },
+       {  83, 286 },
+       {  84, 285 },
+       {  85, 284 },
+       {  86, 283 },
+       {  88, 282 },
+       {  89, 281 },
+       { 256, 280 },
+};
+
+static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
+                                u16 *snr)
+{
+       int i, ret = -EINVAL;
+       dprintk("%s()\n", __func__);
+
+       for (i = 0; i < sz; i++) {
+               if (mse < tab[i].val) {
+                       *snr = tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+       dprintk("%s() snr=%d\n", __func__, *snr);
+       return ret;
+}
+
+/* VSB Modulation table */
+static struct {
+       u16 reg;
+       u16 data;
+} VSB_mod_tab[] = {
+       { 0x8090, 0x84 },
+       { 0x4092, 0x11 },
+       { 0x2005, 0x00 },
+       { 0x8091, 0x80 },
+       { 0x80a3, 0x0c },
+       { 0x80a4, 0xe8 },
+       { 0x8081, 0xc4 },
+       { 0x80a5, 0x40 },
+       { 0x80a7, 0x40 },
+       { 0x80a6, 0x67 },
+       { 0x8262, 0x20 },
+       { 0x821c, 0x30 },
+       { 0x80d8, 0x1a },
+       { 0x8227, 0xa0 },
+       { 0x8121, 0xff },
+       { 0x80a8, 0xf0 },
+       { 0x80a9, 0x05 },
+       { 0x80aa, 0x77 },
+       { 0x80ab, 0xf0 },
+       { 0x80ac, 0x05 },
+       { 0x80ad, 0x77 },
+       { 0x80ae, 0x41 },
+       { 0x80af, 0x66 },
+       { 0x821b, 0xcc },
+       { 0x821d, 0x80 },
+       { 0x80b5, 0xfb },
+       { 0x80b6, 0x8e },
+       { 0x80b7, 0x39 },
+       { 0x80a4, 0xe8 },
+       { 0x8231, 0x13 },
+};
+
+/* QAM Modulation table */
+static struct {
+       u16 reg;
+       u16 data;
+} QAM_mod_tab[] = {
+       { 0x80a3, 0x09 },
+       { 0x80a4, 0x00 },
+       { 0x8081, 0xc4 },
+       { 0x80a5, 0x40 },
+       { 0x80b5, 0xfb },
+       { 0x80b6, 0x8e },
+       { 0x80b7, 0x39 },
+       { 0x80aa, 0x77 },
+       { 0x80ad, 0x77 },
+       { 0x80a6, 0x67 },
+       { 0x8262, 0x20 },
+       { 0x821c, 0x30 },
+       { 0x80b8, 0x3e },
+       { 0x80b9, 0xf0 },
+       { 0x80ba, 0x01 },
+       { 0x80bb, 0x18 },
+       { 0x80bc, 0x50 },
+       { 0x80bd, 0x00 },
+       { 0x80be, 0xea },
+       { 0x80bf, 0xef },
+       { 0x80c0, 0xfc },
+       { 0x80c1, 0xbd },
+       { 0x80c2, 0x1f },
+       { 0x80c3, 0xfc },
+       { 0x80c4, 0xdd },
+       { 0x80c5, 0xaf },
+       { 0x80c6, 0x00 },
+       { 0x80c7, 0x38 },
+       { 0x80c8, 0x30 },
+       { 0x80c9, 0x05 },
+       { 0x80ca, 0x4a },
+       { 0x80cb, 0xd0 },
+       { 0x80cc, 0x01 },
+       { 0x80cd, 0xd9 },
+       { 0x80ce, 0x6f },
+       { 0x80cf, 0xf9 },
+       { 0x80d0, 0x70 },
+       { 0x80d1, 0xdf },
+       { 0x80d2, 0xf7 },
+       { 0x80d3, 0xc2 },
+       { 0x80d4, 0xdf },
+       { 0x80d5, 0x02 },
+       { 0x80d6, 0x9a },
+       { 0x80d7, 0xd0 },
+       { 0x8250, 0x0d },
+       { 0x8251, 0xcd },
+       { 0x8252, 0xe0 },
+       { 0x8253, 0x05 },
+       { 0x8254, 0xa7 },
+       { 0x8255, 0xff },
+       { 0x8256, 0xed },
+       { 0x8257, 0x5b },
+       { 0x8258, 0xae },
+       { 0x8259, 0xe6 },
+       { 0x825a, 0x3d },
+       { 0x825b, 0x0f },
+       { 0x825c, 0x0d },
+       { 0x825d, 0xea },
+       { 0x825e, 0xf2 },
+       { 0x825f, 0x51 },
+       { 0x8260, 0xf5 },
+       { 0x8261, 0x06 },
+       { 0x821a, 0x00 },
+       { 0x8546, 0x40 },
+       { 0x8210, 0x26 },
+       { 0x8211, 0xf6 },
+       { 0x8212, 0x84 },
+       { 0x8213, 0x02 },
+       { 0x8502, 0x01 },
+       { 0x8121, 0x04 },
+       { 0x8122, 0x04 },
+       { 0x852e, 0x10 },
+       { 0x80a4, 0xca },
+       { 0x80a7, 0x40 },
+       { 0x8526, 0x01 },
+};
+
+static int au8522_enable_modulation(struct dvb_frontend *fe,
+                                   fe_modulation_t m)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       int i;
+
+       dprintk("%s(0x%08x)\n", __func__, m);
+
+       switch (m) {
+       case VSB_8:
+               dprintk("%s() VSB_8\n", __func__);
+               for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
+                       au8522_writereg(state,
+                               VSB_mod_tab[i].reg,
+                               VSB_mod_tab[i].data);
+               break;
+       case QAM_64:
+       case QAM_256:
+               dprintk("%s() QAM 64/256\n", __func__);
+               for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+                       au8522_writereg(state,
+                               QAM_mod_tab[i].reg,
+                               QAM_mod_tab[i].data);
+               break;
+       default:
+               dprintk("%s() Invalid modulation\n", __func__);
+               return -EINVAL;
+       }
+
+       state->current_modulation = m;
+
+       return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int au8522_set_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *p)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+       state->current_frequency = p->frequency;
+
+       au8522_enable_modulation(fe, p->u.vsb.modulation);
+
+       /* Allow the demod to settle */
+       msleep(100);
+
+       if (fe->ops.tuner_ops.set_params) {
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int au8522_init(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       dprintk("%s()\n", __func__);
+
+       au8522_writereg(state, 0xa4, 1 << 5);
+
+       au8522_i2c_gate_ctrl(fe, 1);
+
+       return 0;
+}
+
+static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       u8 reg;
+       u32 tuner_status = 0;
+
+       *status = 0;
+
+       if (state->current_modulation == VSB_8) {
+               dprintk("%s() Checking VSB_8\n", __func__);
+               reg = au8522_readreg(state, 0x4088);
+               if (reg & 0x01)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x02)
+                       *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+       } else {
+               dprintk("%s() Checking QAM\n", __func__);
+               reg = au8522_readreg(state, 0x4541);
+               if (reg & 0x80)
+                       *status |= FE_HAS_VITERBI;
+               if (reg & 0x20)
+                       *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+       }
+
+       switch (state->config->status_mode) {
+       case AU8522_DEMODLOCKING:
+               dprintk("%s() DEMODLOCKING\n", __func__);
+               if (*status & FE_HAS_VITERBI)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       case AU8522_TUNERLOCKING:
+               /* Get the tuner status */
+               dprintk("%s() TUNERLOCKING\n", __func__);
+               if (fe->ops.tuner_ops.get_status) {
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+
+                       fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (tuner_status)
+                       *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+               break;
+       }
+
+       dprintk("%s() status 0x%08x\n", __func__, *status);
+
+       return 0;
+}
+
+static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       int ret = -EINVAL;
+
+       dprintk("%s()\n", __func__);
+
+       if (state->current_modulation == QAM_256)
+               ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
+                                           ARRAY_SIZE(qam256_mse2snr_tab),
+                                           au8522_readreg(state, 0x4522),
+                                           snr);
+       else if (state->current_modulation == QAM_64)
+               ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
+                                           ARRAY_SIZE(qam64_mse2snr_tab),
+                                           au8522_readreg(state, 0x4522),
+                                           snr);
+       else /* VSB_8 */
+               ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
+                                           ARRAY_SIZE(vsb_mse2snr_tab),
+                                           au8522_readreg(state, 0x4311),
+                                           snr);
+
+       return ret;
+}
+
+static int au8522_read_signal_strength(struct dvb_frontend *fe,
+                                      u16 *signal_strength)
+{
+       return au8522_read_snr(fe, signal_strength);
+}
+
+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       if (state->current_modulation == VSB_8)
+               *ucblocks = au8522_readreg(state, 0x4087);
+       else
+               *ucblocks = au8522_readreg(state, 0x4543);
+
+       return 0;
+}
+
+static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       return au8522_read_ucblocks(fe, ber);
+}
+
+static int au8522_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *p)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       p->frequency = state->current_frequency;
+       p->u.vsb.modulation = state->current_modulation;
+
+       return 0;
+}
+
+static int au8522_get_tune_settings(struct dvb_frontend *fe,
+                                   struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void au8522_release(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops au8522_ops;
+
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       struct au8522_state *state = NULL;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &au8522_ops,
+              sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       if (au8522_init(&state->frontend) != 0) {
+               printk(KERN_ERR "%s: Failed to initialize correctly\n",
+                       __func__);
+               goto error;
+       }
+
+       /* Note: Leaving the I2C gate open here. */
+       au8522_i2c_gate_ctrl(&state->frontend, 1);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(au8522_attach);
+
+static struct dvb_frontend_ops au8522_ops = {
+
+       .info = {
+               .name                   = "Auvitek AU8522 QAM/8VSB Frontend",
+               .type                   = FE_ATSC,
+               .frequency_min          = 54000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 62500,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+
+       .init                 = au8522_init,
+       .i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
+       .set_frontend         = au8522_set_frontend,
+       .get_frontend         = au8522_get_frontend,
+       .get_tune_settings    = au8522_get_tune_settings,
+       .read_status          = au8522_read_status,
+       .read_ber             = au8522_read_ber,
+       .read_signal_strength = au8522_read_signal_strength,
+       .read_snr             = au8522_read_snr,
+       .read_ucblocks        = au8522_read_ucblocks,
+       .release              = au8522_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
new file mode 100644 (file)
index 0000000..d7affa3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __AU8522_H__
+#define __AU8522_H__
+
+#include <linux/dvb/frontend.h>
+
+struct au8522_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* Return lock status based on tuner lock, or demod lock */
+#define AU8522_TUNERLOCKING 0
+#define AU8522_DEMODLOCKING 1
+       u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_AU8522) ||                              \
+           (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                         struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+                                  struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_AU8522 */
+
+#endif /* __AU8522_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
index a913f49c062b98a46d4fdbf75b38b62b1590083f..d268e65e777d69acdc513e55f705a1064b0e05b8 100644 (file)
@@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
 
                deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, reg,  err);
+                       __func__, state->config->demod_address, reg,  err);
                return -EREMOTEIO;
        }
 
@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
 
        if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
                deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, reg,  err);
+                       __func__, state->config->demod_address, reg,  err);
                return -EREMOTEIO;
        }
        deb_i2c("i2c rd %02x: ",reg);
index 7e4f95e1734b4cf512731ca67b76f616c4a37f38..f4575c0cc446252c7a6413c1f45598a618a0113c 100644 (file)
@@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
 static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_BCM3510
index d8f65738e5d2520e05d2f6508c317fcaadfb4e1f..5e431ebd089b44d997490af145a567608905732e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c)
+ * bsbe1.h - ALPS BSBE1 tuner support
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #define BSBE1_H
 
 static u8 alps_bsbe1_inittab[] = {
-       0x01, 0x15,
-       0x02, 0x30,
-       0x03, 0x00,
+       0x01, 0x15,   /* XTAL = 4MHz, VCO = 352 MHz */
+       0x02, 0x30,   /* MCLK = 88 MHz */
+       0x03, 0x00,   /* ACR output 0 */
        0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-       0x06, 0x40,   /* DAC not used, set to high impendance mode */
-       0x07, 0x00,   /* DAC LSB */
+       0x05, 0x05,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+       0x06, 0x00,   /* DAC output 0 */
        0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
        0x09, 0x00,   /* FIFO */
-       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-       0x10, 0x3f,   // AGC2  0x3d
-       0x11, 0x84,
-       0x12, 0xb9,
-       0x15, 0xc9,   // lock detector threshold
-       0x16, 0x00,
-       0x17, 0x00,
-       0x18, 0x00,
-       0x19, 0x00,
-       0x1a, 0x00,
-       0x1f, 0x50,
-       0x20, 0x00,
-       0x21, 0x00,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
-       0x29, 0x1e,  // 1/2 threshold
-       0x2a, 0x14,  // 2/3 threshold
-       0x2b, 0x0f,  // 3/4 threshold
-       0x2c, 0x09,  // 5/6 threshold
-       0x2d, 0x05,  // 7/8 threshold
-       0x2e, 0x01,
-       0x31, 0x1f,  // test all FECs
-       0x32, 0x19,  // viterbi and synchro search
-       0x33, 0xfc,  // rs control
-       0x34, 0x93,  // error control
-       0x0f, 0x92,
+       0x0c, 0x51,   /* OP1/OP0 normal, val = 1 (LNB power on) */
+       0x0d, 0x82,   /* DC offset compensation = on, beta_agc1 = 2 */
+       0x0f, 0x92,   /* AGC1R */
+       0x10, 0x34,   /* AGC2O */
+       0x11, 0x84,   /* TLSR */
+       0x12, 0xb9,   /* CFD */
+       0x15, 0xc9,   /* lock detector threshold */
+       0x28, 0x00,   /* out imp: normal, type: parallel, FEC mode: QPSK */
+       0x33, 0xfc,   /* RS control */
+       0x34, 0x93,   /* count viterbi bit errors per 2E18 bytes */
        0xff, 0xff
 };
 
@@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
        if ((params->frequency < 950000) || (params->frequency > 2150000))
                return -EINVAL;
 
-       div = (params->frequency + (125 - 1)) / 125; // round correctly
+       div = params->frequency / 1000;
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
-       data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-       data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+       data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
+       data[3] = 0xe0;
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
index e231cd84b3a16a49f4744b1c4b86e9962bcc11a5..45a6dfd8ebb596ea97195a8730cb93abd7a58aff 100644 (file)
@@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_bsru6_set_symbol_rate,
index 11a4968f18cb301be6b5df5676ac2d769ae50631..ace5cb17165daddf0e78c82a08aeaf215b5dec4d 100644 (file)
@@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
        u8 buf [] = { reg, data };
        struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        ret = i2c_transfer (state->i2c, &msg, 1);
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg)
        struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
                           { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        ret = i2c_transfer (state->i2c, msg, 2);
 
@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
 {
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        switch (inversion) {
        case INVERSION_AUTO:
@@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
        static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
                return -EINVAL;
@@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
                                                    FEC_5_6, FEC_7_8 };
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (!(cx22700_readreg(state, 0x07) & 0x20))  /*  tps valid? */
                return -EAGAIN;
index 7ac33690cdcc1144ba268e656f5f528fb3ca52d9..4757a930ca0515426130562ed94c0a7019abb854 100644 (file)
@@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX22700
index 1dc164d5488cd277b3059a19828f98655a7fa86a..cc1db4e371c360c6365ea3ae1b49b91f85d6ab48 100644 (file)
@@ -48,7 +48,7 @@ struct cx22702_state {
        u8 prevUCBlocks;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 /* Register values to initialise the demod */
@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2)
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
 
        return b1[0];
 }
@@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
 static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct cx22702_state* state = fe->demodulator_priv;
-       dprintk ("%s(%d)\n", __FUNCTION__, enable);
+       dprintk ("%s(%d)\n", __func__, enable);
        if (enable)
                return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
        else
@@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
                break;
        default:
-               dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
+               dprintk ("%s: invalid bandwidth\n",__func__);
                return -EINVAL;
        }
 
@@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
                cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
                cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
-               dprintk("%s: Autodetecting\n",__FUNCTION__);
+               dprintk("%s: Autodetecting\n",__func__);
                return 0;
        }
 
@@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case QAM_16: val = (val&0xe7)|0x08; break;
                case QAM_64: val = (val&0xe7)|0x10; break;
                default:
-                       dprintk ("%s: invalid constellation\n",__FUNCTION__);
+                       dprintk ("%s: invalid constellation\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.hierarchy_information) {
@@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case    HIERARCHY_2: val = (val&0xf8)|2; break;
                case    HIERARCHY_4: val = (val&0xf8)|3; break;
                default:
-                       dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
+                       dprintk ("%s: invalid hierarchy\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg (state, 0x06, val);
@@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case FEC_5_6: val = (val&0xc7)|0x18; break;
                case FEC_7_8: val = (val&0xc7)|0x20; break;
                default:
-                       dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__);
+                       dprintk ("%s: invalid code_rate_HP\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.code_rate_LP) {
@@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case FEC_5_6: val = (val&0xf8)|3; break;
                case FEC_7_8: val = (val&0xf8)|4; break;
                default:
-                       dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
+                       dprintk ("%s: invalid code_rate_LP\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg (state, 0x07, val);
@@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                case  GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
                case  GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
                default:
-                       dprintk ("%s: invalid guard_interval\n",__FUNCTION__);
+                       dprintk ("%s: invalid guard_interval\n",__func__);
                        return -EINVAL;
        }
        switch(p->u.ofdm.transmission_mode) {
                case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
                case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
                default:
-                       dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
+                       dprintk ("%s: invalid transmission_mode\n",__func__);
                        return -EINVAL;
        }
        cx22702_writereg(state, 0x08, val);
@@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
        reg23 = cx22702_readreg (state, 0x23);
 
        dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
-               ,__FUNCTION__,reg0A,reg23);
+               ,__func__,reg0A,reg23);
 
        if(reg0A & 0x10) {
                *status |= FE_HAS_LOCK;
index 9cd64da6ee40a3b72b53396911ee7e4eab7eefd7..8af766a315520b882aa7c62adb1f0507d9b6fb69 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX22702
index b03d8283c37d93233dc0d4722dc1fb60a0c9989d..87ae29db024fc2aea18122996b60ac29a879b24d 100644 (file)
@@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
                dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+                        " data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
        static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
        int i;
 
-       dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+       dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
        if (srate>90999000UL/2)
                srate=90999000UL/2;
        if (srate<500000)
@@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 /* fixme (low): error handling */
        int i;
 
-       dprintk("%s: init chip\n", __FUNCTION__);
+       dprintk("%s: init chip\n", __func__);
 
        for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
index 0ca3af4db5136af0108d2fb4ecd5addd89ee8a5e..1792adb23c4d527d89bbb4bd859e01ea4732e854 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX24110
diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
new file mode 100644 (file)
index 0000000..5ab3dd1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satelite)
+ *
+ *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef CX24113_H
+#define CX24113_H
+
+struct dvb_frontend;
+
+struct cx24113_config {
+       u8 i2c_addr; /* 0x14 or 0x54 */
+
+       u32 xtal_khz;
+};
+
+/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
+ * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
+
+static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
+       const struct cx24113_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+static inline void cx24113_agc_callback(struct dvb_frontend *fe)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+#endif /* CX24113_H */
index d74fdbd63361f77e621d1cf1e6d7f4c1b8d5f322..7f68d78c6558eb962ba2b74dbae4b8537faa1825 100644 (file)
@@ -1,24 +1,26 @@
 /*
-    Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
-
-    Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
-
-    Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+ *
+ *   Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+ *
+ *   Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+ *
+ *   Support for CX24123/CX24113-NIM by Patrick Boettcher <pb@linuxtv.org>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
 static int force_band;
 static int debug;
+
+#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
+#define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
+
 #define dprintk(args...) \
        do { \
-               if (debug) printk (KERN_DEBUG "cx24123: " args); \
+               if (debug) { \
+                       printk(KERN_DEBUG "CX24123: %s: ", __func__); \
+                       printk(args); \
+               } \
        } while (0)
 
 struct cx24123_state
@@ -51,6 +60,10 @@ struct cx24123_state
        u32 pllarg;
        u32 FILTune;
 
+       struct i2c_adapter tuner_i2c_adapter;
+
+       u8 demod_rev;
+
        /* The Demod/Tuner can't easily provide these, we cache them */
        u32 currentfreq;
        u32 currentsymbolrate;
@@ -225,48 +238,52 @@ static struct {
        {0x67, 0x83}, /* Non-DCII symbol clock */
 };
 
-static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
+static int cx24123_i2c_writereg(struct cx24123_state *state,
+       u8 i2c_addr, int reg, int data)
 {
        u8 buf[] = { reg, data };
-       struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+       struct i2c_msg msg = {
+               .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+       };
        int err;
 
-       if (debug>1)
-               printk("cx24123: %s:  write reg 0x%02x, value 0x%02x\n",
-                                               __FUNCTION__,reg, data);
+       /* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
                printk("%s: writereg error(err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-               return -EREMOTEIO;
+                        " data == 0x%02x)\n", __func__, err, reg, data);
+               return err;
        }
 
        return 0;
 }
 
-static int cx24123_readreg(struct cx24123_state* state, u8 reg)
+static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
 {
        int ret;
-       u8 b0[] = { reg };
-       u8 b1[] = { 0 };
+       u8 b = 0;
        struct i2c_msg msg[] = {
-               { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-               { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+               { .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
        };
 
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
+               err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
                return ret;
        }
 
-       if (debug>1)
-               printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
+       /* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
 
-       return b1[0];
+       return b;
 }
 
+#define cx24123_readreg(state, reg) \
+       cx24123_i2c_readreg(state, state->config->demod_address, reg)
+#define cx24123_writereg(state, reg, val) \
+       cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
+
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
        u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
 
        switch (inversion) {
        case INVERSION_OFF:
-               dprintk("%s:  inversion off\n",__FUNCTION__);
+               dprintk("inversion off\n");
                cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
                cx24123_writereg(state, 0x10, auto_reg | 0x80);
                break;
        case INVERSION_ON:
-               dprintk("%s:  inversion on\n",__FUNCTION__);
+               dprintk("inversion on\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x80);
                cx24123_writereg(state, 0x10, auto_reg | 0x80);
                break;
        case INVERSION_AUTO:
-               dprintk("%s:  inversion auto\n",__FUNCTION__);
+               dprintk("inversion auto\n");
                cx24123_writereg(state, 0x10, auto_reg & ~0x80);
                break;
        default:
@@ -301,10 +318,10 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
        val = cx24123_readreg(state, 0x1b) >> 7;
 
        if (val == 0) {
-               dprintk("%s:  read inversion off\n",__FUNCTION__);
+               dprintk("read inversion off\n");
                *inversion = INVERSION_OFF;
        } else {
-               dprintk("%s:  read inversion on\n",__FUNCTION__);
+               dprintk("read inversion on\n");
                *inversion = INVERSION_ON;
        }
 
@@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
 
        switch (fec) {
        case FEC_1_2:
-               dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
+               dprintk("set FEC to 1/2\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x01);
                cx24123_writereg(state, 0x0f, 0x02);
                break;
        case FEC_2_3:
-               dprintk("%s:  set FEC to 2/3\n",__FUNCTION__);
+               dprintk("set FEC to 2/3\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x02);
                cx24123_writereg(state, 0x0f, 0x04);
                break;
        case FEC_3_4:
-               dprintk("%s:  set FEC to 3/4\n",__FUNCTION__);
+               dprintk("set FEC to 3/4\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x03);
                cx24123_writereg(state, 0x0f, 0x08);
                break;
        case FEC_4_5:
-               dprintk("%s:  set FEC to 4/5\n",__FUNCTION__);
+               dprintk("set FEC to 4/5\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x04);
                cx24123_writereg(state, 0x0f, 0x10);
                break;
        case FEC_5_6:
-               dprintk("%s:  set FEC to 5/6\n",__FUNCTION__);
+               dprintk("set FEC to 5/6\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x05);
                cx24123_writereg(state, 0x0f, 0x20);
                break;
        case FEC_6_7:
-               dprintk("%s:  set FEC to 6/7\n",__FUNCTION__);
+               dprintk("set FEC to 6/7\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x06);
                cx24123_writereg(state, 0x0f, 0x40);
                break;
        case FEC_7_8:
-               dprintk("%s:  set FEC to 7/8\n",__FUNCTION__);
+               dprintk("set FEC to 7/8\n");
                cx24123_writereg(state, 0x0e, nom_reg | 0x07);
                cx24123_writereg(state, 0x0f, 0x80);
                break;
        case FEC_AUTO:
-               dprintk("%s:  set FEC to auto\n",__FUNCTION__);
+               dprintk("set FEC to auto\n");
                cx24123_writereg(state, 0x0f, 0xfe);
                break;
        default:
@@ -490,7 +507,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
        tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
        cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
 
-       dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
+       dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
+               srate, ratio, sample_rate, sample_gain);
 
        return 0;
 }
@@ -570,7 +588,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        struct cx24123_state *state = fe->demodulator_priv;
        unsigned long timeout;
 
-       dprintk("%s:  pll writereg called, data=0x%08x\n",__FUNCTION__,data);
+       dprintk("pll writereg called, data=0x%08x\n", data);
 
        /* align the 21 bytes into to bit23 boundary */
        data = data << 3;
@@ -583,7 +601,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
        while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding, "\
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -594,7 +613,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data>>8) & 0xff );
        while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding, "\
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -605,7 +625,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_writereg(state, 0x22, (data) & 0xff );
        while ((cx24123_readreg(state, 0x20) & 0x80)) {
                if (time_after(jiffies, timeout)) {
-                       printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+                       err("%s:  demodulator is not responding," \
+                               "possibly hung, aborting.\n", __func__);
                        return -EREMOTEIO;
                }
                msleep(10);
@@ -626,7 +647,7 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
        dprintk("frequency=%i\n", p->frequency);
 
        if (cx24123_pll_calculate(fe, p) != 0) {
-               printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+               err("%s: cx24123_pll_calcutate failed\n", __func__);
                return -EINVAL;
        }
 
@@ -643,18 +664,38 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
        cx24123_writereg(state, 0x27, state->FILTune >> 2);
        cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
 
-       dprintk("%s:  pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
-                       state->bandselectarg,state->pllarg);
+       dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
+                       state->bandselectarg, state->pllarg);
 
        return 0;
 }
 
+
+/*
+ * 0x23:
+ *    [7:7] = BTI enabled
+ *    [6:6] = I2C repeater enabled
+ *    [5:5] = I2C repeater start
+ *    [0:0] = BTI start
+ */
+
+/* mode == 1 -> i2c-repeater, 0 -> bti */
+static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
+{
+       u8 r = cx24123_readreg(state, 0x23) & 0x1e;
+       if (mode)
+               r |= (1 << 6) | (start << 5);
+       else
+               r |= (1 << 7) | (start);
+       return cx24123_writereg(state, 0x23, r);
+}
+
 static int cx24123_initfe(struct dvb_frontend* fe)
 {
        struct cx24123_state *state = fe->demodulator_priv;
        int i;
 
-       dprintk("%s:  init frontend\n",__FUNCTION__);
+       dprintk("init frontend\n");
 
        /* Configure the demod to a good set of defaults */
        for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
@@ -664,6 +705,9 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        if(state->config->lnb_polarity)
                cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
 
+       if (state->config->dont_use_pll)
+       cx24123_repeater_mode(state, 1, 0);
+
        return 0;
 }
 
@@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
-               dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+               dprintk("setting voltage 13V\n");
                return cx24123_writereg(state, 0x29, val & 0x7f);
        case SEC_VOLTAGE_18:
-               dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+               dprintk("setting voltage 18V\n");
                return cx24123_writereg(state, 0x29, val | 0x80);
        case SEC_VOLTAGE_OFF:
                /* already handled in cx88-dvb */
@@ -697,7 +741,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
        unsigned long timeout = jiffies + msecs_to_jiffies(200);
        while (!(cx24123_readreg(state, 0x29) & 0x40)) {
                if(time_after(jiffies, timeout)) {
-                       printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+                       err("%s: diseqc queue not ready, " \
+                               "command may be lost.\n", __func__);
                        break;
                }
                msleep(10);
@@ -709,7 +754,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
        struct cx24123_state *state = fe->demodulator_priv;
        int i, val, tone;
 
-       dprintk("%s:\n",__FUNCTION__);
+       dprintk("\n");
 
        /* stop continuous tone if enabled */
        tone = cx24123_readreg(state, 0x29);
@@ -744,7 +789,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
        struct cx24123_state *state = fe->demodulator_priv;
        int val, tone;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("\n");
 
        /* stop continuous tone if enabled */
        tone = cx24123_readreg(state, 0x29);
@@ -778,13 +823,21 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
 static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-
        int sync = cx24123_readreg(state, 0x14);
-       int lock = cx24123_readreg(state, 0x20);
 
        *status = 0;
-       if (lock & 0x01)
-               *status |= FE_HAS_SIGNAL;
+       if (state->config->dont_use_pll) {
+               u32 tun_status = 0;
+               if (fe->ops.tuner_ops.get_status)
+                       fe->ops.tuner_ops.get_status(fe, &tun_status);
+               if (tun_status & TUNER_STATUS_LOCKED)
+                       *status |= FE_HAS_SIGNAL;
+       } else {
+               int lock = cx24123_readreg(state, 0x20);
+               if (lock & 0x01)
+                       *status |= FE_HAS_SIGNAL;
+       }
+
        if (sync & 0x02)
                *status |= FE_HAS_CARRIER;      /* Phase locked */
        if (sync & 0x04)
@@ -803,7 +856,7 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
  * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
  * is available, so this value doubles up to satisfy both measurements
  */
-static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
                (cx24123_readreg(state, 0x1d) << 8 |
                 cx24123_readreg(state, 0x1e));
 
-       dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
+       dprintk("BER = %d\n", *ber);
 
        return 0;
 }
 
-static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx24123_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
        *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
 
-       dprintk("%s:  Signal strength = %d\n",__FUNCTION__,*signal_strength);
+       dprintk("Signal strength = %d\n", *signal_strength);
 
        return 0;
 }
 
-static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
@@ -838,16 +892,17 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
        *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
                         (u16)cx24123_readreg(state, 0x19));
 
-       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
+       dprintk("read S/N index = %d\n", *snr);
 
        return 0;
 }
 
-static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       dprintk("%s:  set_frontend\n",__FUNCTION__);
+       dprintk("\n");
 
        if (state->config->set_ts_params)
                state->config->set_ts_params(fe, 0);
@@ -858,13 +913,22 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        cx24123_set_inversion(state, p->inversion);
        cx24123_set_fec(state, p->u.qpsk.fec_inner);
        cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
-       cx24123_pll_tune(fe, p);
+
+       if (!state->config->dont_use_pll)
+               cx24123_pll_tune(fe, p);
+       else if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, p);
+       else
+               err("it seems I don't have a tuner...");
 
        /* Enable automatic aquisition and reset cycle */
        cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
        cx24123_writereg(state, 0x00, 0x10);
        cx24123_writereg(state, 0x00, 0);
 
+       if (state->config->agc_callback)
+               state->config->agc_callback(fe);
+
        return 0;
 }
 
@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       dprintk("%s:  get_frontend\n",__FUNCTION__);
+       dprintk("\n");
 
        if (cx24123_get_inversion(state, &p->inversion) != 0) {
-               printk("%s: Failed to get inversion status\n",__FUNCTION__);
+               err("%s: Failed to get inversion status\n", __func__);
                return -EREMOTEIO;
        }
        if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
-               printk("%s: Failed to get fec status\n",__FUNCTION__);
+               err("%s: Failed to get fec status\n", __func__);
                return -EREMOTEIO;
        }
        p->frequency = state->currentfreq;
@@ -900,13 +964,13 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 
        switch (tone) {
        case SEC_TONE_ON:
-               dprintk("%s: setting tone on\n", __FUNCTION__);
+               dprintk("setting tone on\n");
                return cx24123_writereg(state, 0x29, val | 0x10);
        case SEC_TONE_OFF:
-               dprintk("%s: setting tone off\n",__FUNCTION__);
+               dprintk("setting tone off\n");
                return cx24123_writereg(state, 0x29, val & 0xef);
        default:
-               printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+               err("CASE reached default with tone=%d\n", tone);
                return -EINVAL;
        }
 
@@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe)
 static void cx24123_release(struct dvb_frontend* fe)
 {
        struct cx24123_state* state = fe->demodulator_priv;
-       dprintk("%s\n",__FUNCTION__);
+       dprintk("\n");
+       i2c_del_adapter(&state->tuner_i2c_adapter);
        kfree(state);
 }
 
+static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
+       struct i2c_msg msg[], int num)
+{
+       struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
+       /* this repeater closes after the first stop */
+    cx24123_repeater_mode(state, 1, 1);
+       return i2c_transfer(state->i2c, msg, num);
+}
+
+static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx24123_tuner_i2c_algo = {
+       .master_xfer   = cx24123_tuner_i2c_tuner_xfer,
+       .functionality = cx24123_tuner_i2c_func,
+};
+
+struct i2c_adapter *
+       cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+       struct cx24123_state *state = fe->demodulator_priv;
+       return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
+
 static struct dvb_frontend_ops cx24123_ops;
 
 struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
                                    struct i2c_adapter* i2c)
 {
-       struct cx24123_state* state = NULL;
-       int ret;
-
-       dprintk("%s\n",__FUNCTION__);
+       struct cx24123_state *state =
+               kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
 
+       dprintk("\n");
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
        if (state == NULL) {
-               printk("Unable to kmalloc\n");
+               err("Unable to kmalloc\n");
                goto error;
        }
 
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       state->VCAarg = 0;
-       state->VGAarg = 0;
-       state->bandselectarg = 0;
-       state->pllarg = 0;
-       state->currentfreq = 0;
-       state->currentsymbolrate = 0;
 
        /* check if the demod is there */
-       ret = cx24123_readreg(state, 0x00);
-       if ((ret != 0xd1) && (ret != 0xe1)) {
-               printk("Version != d1 or e1\n");
+       state->demod_rev = cx24123_readreg(state, 0x00);
+       switch (state->demod_rev) {
+       case 0xe1: info("detected CX24123C\n"); break;
+       case 0xd1: info("detected CX24123\n"); break;
+       default:
+               err("wrong demod revision: %x\n", state->demod_rev);
                goto error;
        }
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
+
+    /* create tuner i2c adapter */
+    if (config->dont_use_pll)
+       cx24123_repeater_mode(state, 1, 0);
+
+       strncpy(state->tuner_i2c_adapter.name,
+               "CX24123 tuner I2C bus", I2C_NAME_SIZE);
+       state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
+       state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
+       state->tuner_i2c_adapter.algo_data = NULL;
+       i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+       if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+       err("tuner i2c bus could not be initialized\n");
+               goto error;
+       }
+
        return &state->frontend;
 
 error:
@@ -1029,7 +1132,8 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 module_param(force_band, int, 0644);
 MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
 
-MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
+MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
+       "CX24123/CX24109/CX24113 hardware");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
 
index 84f9e4f5c15e1d2750dd7fbb99d15425908060d9..81ebc3d2f19f07353278f00ee82537e48e484c48 100644 (file)
@@ -33,16 +33,27 @@ struct cx24123_config
 
        /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
        int lnb_polarity;
+
+       /* this device has another tuner */
+       u8 dont_use_pll;
+       void (*agc_callback) (struct dvb_frontend *);
 };
 
 #if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
-                                          struct i2c_adapter* i2c);
+extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+                                          struct i2c_adapter *i2c);
+extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
 #else
-static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
-                                                 struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx24123_attach(
+       const struct cx24123_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+static struct i2c_adapter *
+       cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_CX24123
index a6d3854a67bcf6156bf57a9e72de1c5d135d4318..ba917359fa65e16fc5cb4cbd249a13f99c47438d 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config
 static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                                             struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MB
index 72d4757601d81797342a0842219f868177362a79..4142ed7a47d02201e1b5aa13deeeb96f0097f38d 100644 (file)
@@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i
 #else
 static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MC
index 47c23e29753e6dc20dd32ae2d550e8d832d7204c..1a0142e0d74166a5576d11f27f4159403fcd78f0 100644 (file)
@@ -1168,7 +1168,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
        ret = dib7000p_tune(fe, fep);
 
        /* make this a config parameter */
-       dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+       dib7000p_set_output_mode(state, state->cfg.output_mode);
     return ret;
 }
 
@@ -1330,6 +1330,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
        st->gpio_val = cfg->gpio_val;
        st->gpio_dir = cfg->gpio_dir;
 
+       /* Ensure the output mode remains at the previous default if it's
+        * not specifically set by the caller.
+        */
+       if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
+               st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
        demod                   = &st->demod;
        demod->demodulator_priv = st;
        memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
index eefcac8b5244197d0cf9390960a77d8cd954afe5..081bd81f3da2ec5a2b61b797df57ca63b68d8ffe 100644 (file)
@@ -31,6 +31,8 @@ struct dib7000p_config {
        u8 spur_protect;
 
        int (*agc_control) (struct dvb_frontend *, u8 before);
+
+       u8 output_mode;
 };
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
index 8c8d7342d0b37254475d22a804e4680455d5be3a..a054894ff481867842ca344632b3feba1393e729 100644 (file)
@@ -44,14 +44,10 @@ struct dvb_pll_priv {
 
 static unsigned int dvb_pll_devcount;
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
-module_param_array(input, int, NULL, 0644);
-MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
-
 static unsigned int id[DVB_PLL_MAX] =
        { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
 module_param_array(id, int, NULL, 0644);
@@ -80,23 +76,6 @@ struct dvb_pll_desc {
 /* ----------------------------------------------------------- */
 /* descriptions                                                */
 
-/* Set AGC TOP value to 103 dBuV:
-       0x80 = Control Byte
-       0x40 = 250 uA charge pump (irrelevant)
-       0x18 = Aux Byte to follow
-       0x06 = 64.5 kHz divider (irrelevant)
-       0x01 = Disable Vt (aka sleep)
-
-       0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
-       0x50 = AGC Take over point = 103 dBuV */
-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
-
-/*     0x04 = 166.67 kHz divider
-
-       0x80 = AGC Time constant 50ms Iagc = 9 uA
-       0x20 = AGC Take over point = 112 dBuV */
-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
-
 static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        .name  = "Thomson dtt7579",
        .min   = 177000000,
@@ -112,19 +91,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        },
 };
 
-static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
-       .name  = "Thomson dtt7610",
-       .min   =  44000000,
-       .max   = 958000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 157250000, 62500, 0x8e, 0x39 },
-               { 454000000, 62500, 0x8e, 0x3a },
-               { 999999999, 62500, 0x8e, 0x3c },
-       },
-};
-
 static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
                               const struct dvb_frontend_parameters *params)
 {
@@ -165,34 +131,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
        },
 };
 
-static struct dvb_pll_desc dvb_pll_microtune_4042 = {
-       .name  = "Microtune 4042 FI5",
-       .min   =  57000000,
-       .max   = 858000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 162000000, 62500, 0x8e, 0xa1 },
-               { 457000000, 62500, 0x8e, 0x91 },
-               { 999999999, 62500, 0x8e, 0x31 },
-       },
-};
-
-static struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
-       /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
-       .name  = "Thomson dtt761x",
-       .min   =  57000000,
-       .max   = 863000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .initdata = tua603x_agc103,
-       .entries = {
-               { 147000000, 62500, 0x8e, 0x39 },
-               { 417000000, 62500, 0x8e, 0x3a },
-               { 999999999, 62500, 0x8e, 0x3c },
-       },
-};
-
 static struct dvb_pll_desc dvb_pll_unknown_1 = {
        .name  = "unknown 1", /* used by dntv live dvb-t */
        .min   = 174000000,
@@ -301,54 +239,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
        },
 };
 
-/* Infineon TUA6034
- * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
- */
-static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
-       .name  = "LG TDVS-H06xF",
-       .min   =  54000000,
-       .max   = 863000000,
-       .iffreq= 44000000,
-       .initdata = tua603x_agc103,
-       .count = 3,
-       .entries = {
-               {  165000000, 62500, 0xce, 0x01 },
-               {  450000000, 62500, 0xce, 0x02 },
-               {  999999999, 62500, 0xce, 0x04 },
-       },
-};
-
-/* Philips FMD1216ME
- * used in Medion Hybrid PCMCIA card and USB Box
- */
-static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
-                        const struct dvb_frontend_parameters *params)
-{
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
-           params->frequency >= 158870000)
-               buf[3] |= 0x08;
-}
-
-static struct dvb_pll_desc dvb_pll_fmd1216me = {
-       .name = "Philips FMD1216ME",
-       .min = 50870000,
-       .max = 858000000,
-       .iffreq= 36125000,
-       .set   = fmd1216me_bw,
-       .initdata = tua603x_agc112,
-       .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
-       .count = 7,
-       .entries = {
-               { 143870000, 166667, 0xbc, 0x41 },
-               { 158870000, 166667, 0xf4, 0x41 },
-               { 329870000, 166667, 0xbc, 0x42 },
-               { 441870000, 166667, 0xf4, 0x42 },
-               { 625870000, 166667, 0xbc, 0x44 },
-               { 803870000, 166667, 0xf4, 0x44 },
-               { 999999999, 166667, 0xfc, 0x44 },
-       }
-};
-
 /* ALPS TDED4
  * used in Nebula-Cards and USB boxes
  */
@@ -391,55 +281,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
        }
 };
 
-/* Philips TUV1236D
- * used in ATI HDTV Wonder
- */
-static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
-                       const struct dvb_frontend_parameters *params)
-{
-       struct dvb_pll_priv *priv = fe->tuner_priv;
-       unsigned int new_rf = input[priv->nr];
-
-       if ((new_rf == 0) || (new_rf > 2)) {
-               switch (params->u.vsb.modulation) {
-                       case QAM_64:
-                       case QAM_256:
-                               new_rf = 1;
-                               break;
-                       case VSB_8:
-                       default:
-                               new_rf = 2;
-               }
-       }
-
-       switch (new_rf) {
-               case 1:
-                       buf[3] |= 0x08;
-                       break;
-               case 2:
-                       buf[3] &= ~0x08;
-                       break;
-               default:
-                       printk(KERN_WARNING
-                              "%s: unhandled rf input selection: %d",
-                              __FUNCTION__, new_rf);
-       }
-}
-
-static struct dvb_pll_desc dvb_pll_tuv1236d = {
-       .name  = "Philips TUV1236D",
-       .min   =  54000000,
-       .max   = 864000000,
-       .iffreq= 44000000,
-       .set   = tuv1236d_rf,
-       .count = 3,
-       .entries = {
-               { 157250000, 62500, 0xc6, 0x41 },
-               { 454000000, 62500, 0xc6, 0x42 },
-               { 999999999, 62500, 0xc6, 0x44 },
-       },
-};
-
 /* Samsung TBMV30111IN / TBMV30712IN1
  * used in Air2PC ATSC - 2nd generation (nxt2002)
  */
@@ -476,64 +317,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
        },
 };
 
-/*
- * Philips TD1316 Tuner.
- */
-static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
-                     const struct dvb_frontend_parameters *params)
-{
-       u8 band;
-
-       /* determine band */
-       if (params->frequency < 161000000)
-               band = 1;
-       else if (params->frequency < 444000000)
-               band = 2;
-       else
-               band = 4;
-
-       buf[3] |= band;
-
-       /* setup PLL filter */
-       if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
-               buf[3] |= 1 << 3;
-}
-
-static struct dvb_pll_desc dvb_pll_philips_td1316 = {
-       .name  = "Philips TD1316",
-       .min   =  87000000,
-       .max   = 895000000,
-       .iffreq= 36166667,
-       .set   = td1316_bw,
-       .count = 9,
-       .entries = {
-               {  93834000, 166667, 0xca, 0x60},
-               { 123834000, 166667, 0xca, 0xa0},
-               { 163834000, 166667, 0xca, 0xc0},
-               { 253834000, 166667, 0xca, 0x60},
-               { 383834000, 166667, 0xca, 0xa0},
-               { 443834000, 166667, 0xca, 0xc0},
-               { 583834000, 166667, 0xca, 0x60},
-               { 793834000, 166667, 0xca, 0xa0},
-               { 858834000, 166667, 0xca, 0xe0},
-       },
-};
-
-/* FE6600 used on DViCO Hybrid */
-static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
-       .name = "Thomson FE6600",
-       .min =  44250000,
-       .max = 858000000,
-       .iffreq= 36125000,
-       .count = 4,
-       .entries = {
-               { 250000000, 166667, 0xb4, 0x12 },
-               { 455000000, 166667, 0xfe, 0x11 },
-               { 775500000, 166667, 0xbc, 0x18 },
-               { 999999999, 166667, 0xf4, 0x18 },
-       }
-};
-
 static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
                      const struct dvb_frontend_parameters *params)
 {
@@ -560,50 +343,23 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
        }
 };
 
-/* Philips FCV1236D
- */
-static struct dvb_pll_desc dvb_pll_fcv1236d = {
-/* Bit_0: RF Input select
- * Bit_1: 0=digital, 1=analog
- */
-       .name  = "Philips FCV1236D",
-       .min   =  53000000,
-       .max   = 803000000,
-       .iffreq= 44000000,
-       .count = 3,
-       .entries = {
-               { 159000000, 62500, 0x8e, 0xa0 },
-               { 453000000, 62500, 0x8e, 0x90 },
-               { 999999999, 62500, 0x8e, 0x30 },
-       },
-};
-
 /* ----------------------------------------------------------- */
 
 static struct dvb_pll_desc *pll_list[] = {
        [DVB_PLL_UNDEFINED]              = NULL,
        [DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
        [DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
-       [DVB_PLL_THOMSON_DTT7610]        = &dvb_pll_thomson_dtt7610,
        [DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
-       [DVB_PLL_MICROTUNE_4042]         = &dvb_pll_microtune_4042,
-       [DVB_PLL_THOMSON_DTT761X]        = &dvb_pll_thomson_dtt761x,
        [DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
        [DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
        [DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
        [DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
-       [DVB_PLL_LG_TDVS_H06XF]          = &dvb_pll_lg_tdvs_h06xf,
        [DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
-       [DVB_PLL_FMD1216ME]              = &dvb_pll_fmd1216me,
        [DVB_PLL_TDED4]                  = &dvb_pll_tded4,
-       [DVB_PLL_TUV1236D]               = &dvb_pll_tuv1236d,
        [DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
        [DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
        [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
-       [DVB_PLL_PHILIPS_TD1316]         = &dvb_pll_philips_td1316,
-       [DVB_PLL_THOMSON_FE6600]         = &dvb_pll_thomson_fe6600,
        [DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
-       [DVB_PLL_FCV1236D]               = &dvb_pll_fcv1236d,
 };
 
 /* ----------------------------------------------------------- */
@@ -849,20 +605,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
                       id[priv->nr] == pll_desc_id ?
                                "insmod option" : "autodetected");
        }
-       if ((debug) || (input[priv->nr] > 0)) {
-               printk("dvb-pll[%d]", priv->nr);
-               if (i2c != NULL)
-                       printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
-               printk(": tuner rf input will be ");
-               switch (input[priv->nr]) {
-               case 0:
-                       printk("autoselected\n");
-                       break;
-               default:
-                       printk("set to input %d (insmod option)\n",
-                              input[priv->nr]);
-               }
-       }
 
        return fe;
 }
index e93a8104052bb12b9ff5257d902798a27396aac0..872ca29e7cf37db7af523619637b24f2951c7408 100644 (file)
 #define DVB_PLL_UNDEFINED               0
 #define DVB_PLL_THOMSON_DTT7579         1
 #define DVB_PLL_THOMSON_DTT759X         2
-#define DVB_PLL_THOMSON_DTT7610         3
-#define DVB_PLL_LG_Z201                 4
-#define DVB_PLL_MICROTUNE_4042          5
-#define DVB_PLL_THOMSON_DTT761X         6
-#define DVB_PLL_UNKNOWN_1               7
-#define DVB_PLL_TUA6010XS               8
-#define DVB_PLL_ENV57H1XD5              9
-#define DVB_PLL_TUA6034                10
-#define DVB_PLL_LG_TDVS_H06XF          11
-#define DVB_PLL_TDA665X                12
-#define DVB_PLL_FMD1216ME              13
-#define DVB_PLL_TDED4                  14
-#define DVB_PLL_TUV1236D               15
-#define DVB_PLL_TDHU2                  16
-#define DVB_PLL_SAMSUNG_TBMV           17
-#define DVB_PLL_PHILIPS_SD1878_TDA8261 18
-#define DVB_PLL_PHILIPS_TD1316         19
-#define DVB_PLL_THOMSON_FE6600         20
-#define DVB_PLL_OPERA1                 21
-#define DVB_PLL_FCV1236D               22
+#define DVB_PLL_LG_Z201                 3
+#define DVB_PLL_UNKNOWN_1               4
+#define DVB_PLL_TUA6010XS               5
+#define DVB_PLL_ENV57H1XD5              6
+#define DVB_PLL_TUA6034                 7
+#define DVB_PLL_TDA665X                 8
+#define DVB_PLL_TDED4                   9
+#define DVB_PLL_TDHU2                  10
+#define DVB_PLL_SAMSUNG_TBMV           11
+#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
+#define DVB_PLL_OPERA1                 13
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
@@ -52,7 +43,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
                                           struct i2c_adapter *i2c,
                                           unsigned int pll_desc_id)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c
new file mode 100644 (file)
index 0000000..33d33f4
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * isl6405.c - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6405.h"
+
+struct isl6405 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       u8                      i2c_addr;
+};
+
+static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+       struct i2c_msg msg = {  .addr = isl6405->i2c_addr, .flags = 0,
+                               .buf = &isl6405->config,
+                               .len = sizeof(isl6405->config) };
+
+       if (isl6405->override_or & 0x80) {
+               isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
+               switch (voltage) {
+               case SEC_VOLTAGE_OFF:
+                       break;
+               case SEC_VOLTAGE_13:
+                       isl6405->config |= ISL6405_EN2;
+                       break;
+               case SEC_VOLTAGE_18:
+                       isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
+               switch (voltage) {
+               case SEC_VOLTAGE_OFF:
+                       break;
+               case SEC_VOLTAGE_13:
+                       isl6405->config |= ISL6405_EN1;
+                       break;
+               case SEC_VOLTAGE_18:
+                       isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
+                       break;
+               default:
+                       return -EINVAL;
+               };
+       }
+       isl6405->config |= isl6405->override_or;
+       isl6405->config &= isl6405->override_and;
+
+       return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+       struct i2c_msg msg = {  .addr = isl6405->i2c_addr, .flags = 0,
+                               .buf = &isl6405->config,
+                               .len = sizeof(isl6405->config) };
+
+       if (isl6405->override_or & 0x80) {
+               if (arg)
+                       isl6405->config |= ISL6405_LLC2;
+               else
+                       isl6405->config &= ~ISL6405_LLC2;
+       } else {
+               if (arg)
+                       isl6405->config |= ISL6405_LLC1;
+               else
+                       isl6405->config &= ~ISL6405_LLC1;
+       }
+       isl6405->config |= isl6405->override_or;
+       isl6405->config &= isl6405->override_and;
+
+       return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6405_release(struct dvb_frontend *fe)
+{
+       /* power off */
+       isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+                                   u8 i2c_addr, u8 override_set, u8 override_clear)
+{
+       struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
+       if (!isl6405)
+               return NULL;
+
+       /* default configuration */
+       if (override_set & 0x80)
+               isl6405->config = ISL6405_ISEL2;
+       else
+               isl6405->config = ISL6405_ISEL1;
+       isl6405->i2c = i2c;
+       isl6405->i2c_addr = i2c_addr;
+       fe->sec_priv = isl6405;
+
+       /* bits which should be forced to '1' */
+       isl6405->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       isl6405->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(isl6405);
+               fe->sec_priv = NULL;
+               return NULL;
+       }
+
+       /* install release callback */
+       fe->ops.release_sec = isl6405_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = isl6405_set_voltage;
+       fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
+
+       return fe;
+}
+EXPORT_SYMBOL(isl6405_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
+MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h
new file mode 100644 (file)
index 0000000..1c793d3
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * isl6405.h - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6405_H
+#define _ISL6405_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+
+/* this bit selects register (control) 1 or 2
+   note that the bit maps are different */
+
+#define ISL6405_SR     0x80
+
+/* SR = 0 */
+#define ISL6405_OLF1   0x01
+#define ISL6405_EN1    0x02
+#define ISL6405_VSEL1  0x04
+#define ISL6405_LLC1   0x08
+#define ISL6405_ENT1   0x10
+#define ISL6405_ISEL1  0x20
+#define ISL6405_DCL    0x40
+
+/* SR = 1 */
+#define ISL6405_OLF2   0x01
+#define ISL6405_OTF    0x02
+#define ISL6405_EN2    0x04
+#define ISL6405_VSEL2  0x08
+#define ISL6405_LLC2   0x10
+#define ISL6405_ENT2   0x20
+#define ISL6405_ISEL2  0x40
+
+#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
+/* override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+                                          u8 i2c_addr, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
+                                                 struct i2c_adapter *i2c, u8 i2c_addr,
+                                                 u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_ISL6405 */
+
+#endif
index ea7f78a7d3cd41bce664a6176d922d520c28a5ff..47e4518a042de6b688332df6ff6ca21b38c74844 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a
 static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                                                  u8 override_set, u8 override_clear)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_ISL6421
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
new file mode 100644 (file)
index 0000000..04c562c
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "itd1000.h"
+#include "itd1000_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define deb(args...)  do { \
+       if (debug) { \
+               printk(KERN_DEBUG   "ITD1000: " args);\
+               printk("\n"); \
+       } \
+} while (0)
+
+#define warn(args...) do { \
+       printk(KERN_WARNING "ITD1000: " args); \
+       printk("\n"); \
+} while (0)
+
+#define info(args...) do { \
+       printk(KERN_INFO    "ITD1000: " args); \
+       printk("\n"); \
+} while (0)
+
+/* don't write more than one byte with flexcop behind */
+static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
+{
+       u8 buf[1+len];
+       struct i2c_msg msg = {
+               .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
+       };
+       buf[0] = reg;
+       memcpy(&buf[1], v, len);
+
+       /* deb("wr %02x: %02x", reg, v[0]); */
+
+       if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "itd1000 I2C write failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
+{
+       u8 val;
+       struct i2c_msg msg[2] = {
+               { .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+               { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
+       };
+
+       /* ugly flexcop workaround */
+       itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
+
+       if (i2c_transfer(state->i2c, msg, 2) != 2) {
+               warn("itd1000 I2C read failed");
+               return -EREMOTEIO;
+       }
+       return val;
+}
+
+static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
+{
+       int ret = itd1000_write_regs(state, r, &v, 1);
+       state->shadow[r] = v;
+       return ret;
+}
+
+
+static struct {
+       u32 symbol_rate;
+       u8  pgaext  : 4; /* PLLFH */
+       u8  bbgvmin : 4; /* BBGVMIN */
+} itd1000_lpf_pga[] = {
+       {        0, 0x8, 0x3 },
+       {  5200000, 0x8, 0x3 },
+       { 12200000, 0x4, 0x3 },
+       { 15400000, 0x2, 0x3 },
+       { 19800000, 0x2, 0x3 },
+       { 21500000, 0x2, 0x3 },
+       { 24500000, 0x2, 0x3 },
+       { 28400000, 0x2, 0x3 },
+       { 33400000, 0x2, 0x3 },
+       { 34400000, 0x1, 0x4 },
+       { 34400000, 0x1, 0x4 },
+       { 38400000, 0x1, 0x4 },
+       { 38400000, 0x1, 0x4 },
+       { 40400000, 0x1, 0x4 },
+       { 45400000, 0x1, 0x4 },
+};
+
+static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
+{
+       u8 i;
+       u8 con1    = itd1000_read_reg(state, CON1)    & 0xfd;
+       u8 pllfh   = itd1000_read_reg(state, PLLFH)   & 0x0f;
+       u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
+       u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
+
+       deb("symbol_rate = %d", symbol_rate);
+
+       /* not sure what is that ? - starting to download the table */
+       itd1000_write_reg(state, CON1, con1 | (1 << 1));
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
+               if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
+                       deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+                       itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
+                       itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
+                       itd1000_write_reg(state, BW,      bw | (i & 0x0f));
+                       break;
+               }
+
+       itd1000_write_reg(state, CON1, con1 | (0 << 1));
+}
+
+static struct {
+       u8 vcorg;
+       u32 fmax_rg;
+} itd1000_vcorg[] = {
+       {  1,  920000 },
+       {  2,  971000 },
+       {  3, 1031000 },
+       {  4, 1091000 },
+       {  5, 1171000 },
+       {  6, 1281000 },
+       {  7, 1381000 },
+       {  8,  500000 },        /* this is intentional. */
+       {  9, 1451000 },
+       { 10, 1531000 },
+       { 11, 1631000 },
+       { 12, 1741000 },
+       { 13, 1891000 },
+       { 14, 2071000 },
+       { 15, 2250000 },
+};
+
+static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
+{
+       u8 i;
+       u8 gvbb_i2c     = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
+       u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
+       u8 adcout;
+
+       /* reserved bit again (reset ?) */
+       itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
+               if (freq_khz < itd1000_vcorg[i].fmax_rg) {
+                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
+                       msleep(1);
+
+                       adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
+
+                       deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+
+                       if (adcout > 13) {
+                               if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
+                                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
+                       } else if (adcout < 2) {
+                               if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
+                                       itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
+                       }
+                       break;
+               }
+       }
+}
+
+struct {
+       u32 freq;
+       u8 values[10]; /* RFTR, RFST1 - RFST9 */
+} itd1000_fre_values[] = {
+       { 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+       { 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
+       { 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
+       { 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
+};
+
+
+#define FREF 16
+
+static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
+{
+       int i, j;
+       u32 plln, pllf;
+       u64 tmp;
+
+       plln = (freq_khz * 1000) / 2 / FREF;
+
+       /* Compute the factional part times 1000 */
+       tmp  = plln % 1000000;
+       plln /= 1000000;
+
+       tmp *= 1048576;
+       do_div(tmp, 1000000);
+       pllf = (u32) tmp;
+
+       state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
+       deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
+
+       itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+       itd1000_write_reg(state, PLLNL, plln & 0xff);
+       itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
+       itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
+       itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
+               if (freq_khz <= itd1000_fre_values[i].freq) {
+                       deb("fre_values: %d", i);
+                       itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
+                       for (j = 0; j < 9; j++)
+                               itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
+                       break;
+               }
+       }
+
+       itd1000_set_vco(state, freq_khz);
+}
+
+static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       u8 pllcon1;
+
+       itd1000_set_lo(state, p->frequency);
+       itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
+
+       pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
+       itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
+       itd1000_write_reg(state, PLLCON1, pllcon1);
+
+       return 0;
+}
+
+static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       *frequency = state->frequency;
+       return 0;
+}
+
+static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       return 0;
+}
+
+static u8 itd1000_init_tab[][2] = {
+       { PLLCON1,       0x65 }, /* Register does not change */
+       { PLLNH,         0x80 }, /* Bits [7:6] do not change */
+       { RESERVED_0X6D, 0x3b },
+       { VCO_CHP2_I2C,  0x12 },
+       { 0x72,          0xf9 }, /* No such regsister defined */
+       { RESERVED_0X73, 0xff },
+       { RESERVED_0X74, 0xb2 },
+       { RESERVED_0X75, 0xc7 },
+       { EXTGVBBRF,     0xf0 },
+       { DIVAGCCK,      0x80 },
+       { BBTR,          0xa0 },
+       { RESERVED_0X7E, 0x4f },
+       { 0x82,          0x88 }, /* No such regsister defined */
+       { 0x83,          0x80 }, /* No such regsister defined */
+       { 0x84,          0x80 }, /* No such regsister defined */
+       { RESERVED_0X85, 0x74 },
+       { RESERVED_0X86, 0xff },
+       { RESERVED_0X88, 0x02 },
+       { RESERVED_0X89, 0x16 },
+       { RFST0,         0x1f },
+       { RESERVED_0X94, 0x66 },
+       { RESERVED_0X95, 0x66 },
+       { RESERVED_0X96, 0x77 },
+       { RESERVED_0X97, 0x99 },
+       { RESERVED_0X98, 0xff },
+       { RESERVED_0X99, 0xfc },
+       { RESERVED_0X9A, 0xba },
+       { RESERVED_0X9B, 0xaa },
+};
+
+static u8 itd1000_reinit_tab[][2] = {
+       { VCO_CHP1_I2C, 0x8a },
+       { BW,           0x87 },
+       { GVBB_I2C,     0x03 },
+       { BBGVMIN,      0x03 },
+       { CON1,         0x2e },
+};
+
+
+static int itd1000_init(struct dvb_frontend *fe)
+{
+       struct itd1000_state *state = fe->tuner_priv;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
+               itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
+
+       for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
+               itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
+
+       return 0;
+}
+
+static int itd1000_sleep(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static int itd1000_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static const struct dvb_tuner_ops itd1000_tuner_ops = {
+       .info = {
+               .name           = "Integrant ITD1000",
+               .frequency_min  = 950000,
+               .frequency_max  = 2150000,
+               .frequency_step = 125,     /* kHz for QPSK frontends */
+       },
+
+       .release       = itd1000_release,
+
+       .init          = itd1000_init,
+       .sleep         = itd1000_sleep,
+
+       .set_params    = itd1000_set_parameters,
+       .get_frequency = itd1000_get_frequency,
+       .get_bandwidth = itd1000_get_bandwidth
+};
+
+
+struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+       struct itd1000_state *state = NULL;
+       u8 i = 0;
+
+       state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
+       if (state == NULL)
+               return NULL;
+
+       state->cfg = cfg;
+       state->i2c = i2c;
+
+       i = itd1000_read_reg(state, 0);
+       if (i != 0) {
+               kfree(state);
+               return NULL;
+       }
+       info("successfully identified (ID: %d)", i);
+
+       memset(state->shadow, 0xff, sizeof(state->shadow));
+       for (i = 0x65; i < 0x9c; i++)
+               state->shadow[i] = itd1000_read_reg(state, i);
+
+       memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = state;
+
+       return fe;
+}
+EXPORT_SYMBOL(itd1000_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("Integrant ITD1000 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
new file mode 100644 (file)
index 0000000..5e18df0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_H
+#define ITD1000_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct itd1000_config {
+       u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
+#else
+static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
new file mode 100644 (file)
index 0000000..8cdc54e
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_PRIV_H
+#define ITD1000_PRIV_H
+
+struct itd1000_state {
+       struct itd1000_config *cfg;
+       struct i2c_adapter    *i2c;
+
+       u32 frequency; /* contains the value resulting from the LO-setting */
+
+       /* ugly workaround for flexcop's incapable i2c-controller
+        * FIXME, if possible
+        */
+       u8 shadow[255];
+};
+
+enum itd1000_register {
+       VCO_CHP1 = 0x65,
+       VCO_CHP2,
+       PLLCON1,
+       PLLNH,
+       PLLNL,
+       PLLFH,
+       PLLFM,
+       PLLFL,
+       RESERVED_0X6D,
+       PLLLOCK,
+       VCO_CHP2_I2C,
+       VCO_CHP1_I2C,
+       BW,
+       RESERVED_0X73 = 0x73,
+       RESERVED_0X74,
+       RESERVED_0X75,
+       GVBB,
+       GVRF,
+       GVBB_I2C,
+       EXTGVBBRF,
+       DIVAGCCK,
+       BBTR,
+       RFTR,
+       BBGVMIN,
+       RESERVED_0X7E,
+       RESERVED_0X85 = 0x85,
+       RESERVED_0X86,
+       CON1,
+       RESERVED_0X88,
+       RESERVED_0X89,
+       RFST0,
+       RFST1,
+       RFST2,
+       RFST3,
+       RFST4,
+       RFST5,
+       RFST6,
+       RFST7,
+       RFST8,
+       RFST9,
+       RESERVED_0X94,
+       RESERVED_0X95,
+       RESERVED_0X96,
+       RESERVED_0X97,
+       RESERVED_0X98,
+       RESERVED_0X99,
+       RESERVED_0X9A,
+       RESERVED_0X9B,
+};
+
+#endif
index 443d9045d4c9b8d93ec8fa2f53a18f9351166d6c..e1e70e9e0cb9ced61f4b71f96a882bff38d40965 100644 (file)
@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
 
        if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
                dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
-                        __FUNCTION__, reg, ret);
+                        __func__, reg, ret);
 
        return (ret != 1) ? -1 : 0;
 }
index cd15f76ff28da22f6ae1157ec7d3871a9dfb4f21..1305a9e7fb0b543bab0c18d3e05655cd67c2c7bf 100644 (file)
@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_L64781
index bdc9fa88b86afc93128f43de48adabfb1818bca2..f0195c8272f4486c4c67d402025f50e0bfe64d75 100644 (file)
@@ -49,7 +49,7 @@
 /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
 /* #define USE_EQMSE */
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
 #define dprintk(args...) \
@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
 
        for (i=0; i<len-1; i+=2){
                if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
+                       printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
                        if (err < 0)
                                return err;
                        else
@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
        int ret;
        ret = i2c_transfer(state->i2c, msg, 2);
        if (ret != 2) {
-               printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
+               printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
        } else {
                ret = 0;
        }
@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
                err = -ENODEV;
        }
-       dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+       dprintk("%s entered as %s\n", __func__, chip_name);
        if (err < 0)
                return err;
        return lgdt330x_SwReset(state);
@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        if (state->current_modulation != param->u.vsb.modulation) {
                switch(param->u.vsb.modulation) {
                case VSB_8:
-                       dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
+                       dprintk("%s: VSB_8 MODE\n", __func__);
 
                        /* Select VSB mode */
                        top_ctrl_cfg[1] = 0x03;
@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        break;
 
                case QAM_64:
-                       dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
+                       dprintk("%s: QAM_64 MODE\n", __func__);
 
                        /* Select QAM_64 mode */
                        top_ctrl_cfg[1] = 0x00;
@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        break;
 
                case QAM_256:
-                       dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
+                       dprintk("%s: QAM_256 MODE\n", __func__);
 
                        /* Select QAM_256 mode */
                        top_ctrl_cfg[1] = 0x01;
@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
                        }
                        break;
                default:
-                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
+                       printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
                        return -1;
                }
                /*
@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* AGC status register */
        i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
-       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
        if ((buf[0] & 0x0c) == 0x8){
                /* Test signal does not exist flag */
                /* as well as the AGC lock flag.   */
@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
         */
        /* signal status */
        i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
-       dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
+       dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
 
 
        /* sync status */
@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* Carrier Recovery Lock Status Register */
        i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
        switch (state->current_modulation) {
        case QAM_256:
        case QAM_64:
@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
                        *status |= FE_HAS_CARRIER;
                break;
        default:
-               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
        }
 
        return 0;
@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
        if (err < 0)
                return err;
 
-       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
        if ((buf[0] & 0x21) == 0x01){
                /* Test input signal does not exist flag */
                /* as well as the AGC lock flag.   */
@@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* Carrier Recovery Lock Status Register */
        i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
        switch (state->current_modulation) {
        case QAM_256:
        case QAM_64:
@@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
                }
                break;
        default:
-               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+               printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
        }
        return 0;
 }
@@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
                break;
        default:
                printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-                      __FUNCTION__);
+                      __func__);
                return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
        state->snr = calculate_snr(noise, c);
        *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
@@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
                break;
        default:
                printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-                      __FUNCTION__);
+                      __func__);
                return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
        }
 
        state->snr = calculate_snr(noise, c);
        *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
 
        return 0;
@@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 
 error:
        kfree(state);
-       dprintk("%s: ERROR\n",__FUNCTION__);
+       dprintk("%s: ERROR\n",__func__);
        return NULL;
 }
 
index 995059004b109918a9909b2dfb607030129273c7..9012504f0f2d523523ff2e3dbc0b1cca2dcd7086 100644 (file)
@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
 static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_LGDT330X
index 68906acf7d63d75405ad58340d5a5752a0dd63e9..8fe094bd9689a1e793ce2d553abc5a306c9143c5 100644 (file)
@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
 #else
 static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_LNBP21
index 0a86eab3a954d376d27a0ba4a9624a7692567380..acba0058f519bf00403a78b56b369de56f8c6a9c 100644 (file)
@@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a
 #else
 static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_MT2060
index 13cf16668171bb611b73ac143e7a77bfcf34b89e..e254bcfc2efb77df010cdae10d482eaeb884afb4 100644 (file)
@@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
                priv->bandwidth = 0;
 
        freq = params->frequency / 1000;  // Hz -> kHz
-       dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
+       dprintk(1, "%s() freq=%d\n", __func__, freq);
 
        f_lo1 = freq + MT2131_IF1 * 1000;
        f_lo1 = (f_lo1 / 250) * 250;
@@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
 static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *frequency = priv->frequency;
        return 0;
 }
@@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *bandwidth = priv->bandwidth;
        return 0;
 }
@@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
 
        mt2131_readreg(priv, 0x09, &afc_status);
        dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
-               __FUNCTION__, lock_status, afc_status);
+               __func__, lock_status, afc_status);
 
        return 0;
 }
@@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe)
 {
        struct mt2131_priv *priv = fe->tuner_priv;
        int ret;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if ((ret = mt2131_writeregs(priv, mt2131_config1,
                                    sizeof(mt2131_config1))) < 0)
@@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe)
 
 static int mt2131_release(struct dvb_frontend *fe)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
@@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
        struct mt2131_priv *priv = NULL;
        u8 id = 0;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
        if (priv == NULL)
index 1e4ffe7dc8c89ead1f5c5c1b529bf6f7b6549510..606d8576bc9885d2a7d8a9c504d41efcb860be76 100644 (file)
@@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
                                                 struct mt2131_config *cfg,
                                                 u16 if1)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_TUNER_MT2131 */
index f31dd613ad37979005babdfb2c65c0c46cf6d9c1..c5113efe333c745a0e66919827a88b42073f3719 100644 (file)
@@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a
 #else
 static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_MT2266
index 1638301fbd6e71268812f48beddc1cea1b0cb127..081ca3398c76b074012f4fa99d7f41910d30e165 100644 (file)
@@ -1,7 +1,8 @@
 /*
-    Driver for Zarlink VP310/MT312 Satellite Channel Decoder
+    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
 
     Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
+    Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -43,7 +44,8 @@ struct mt312_state {
        struct dvb_frontend frontend;
 
        u8 id;
-       u8 frequency;
+       unsigned long xtal;
+       u8 freq_mult;
 };
 
 static int debug;
@@ -53,12 +55,11 @@ static int debug;
                        printk(KERN_DEBUG "mt312: " args); \
        } while (0)
 
-#define MT312_SYS_CLK          90000000UL      /* 90 MHz */
-#define MT312_LPOWER_SYS_CLK   60000000UL      /* 60 MHz */
 #define MT312_PLL_CLK          10000000UL      /* 10 MHz */
+#define MT312_PLL_CLK_10_111   10111000UL      /* 10.111 MHz */
 
 static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
-                     void *buf, const size_t count)
+                     u8 *buf, const size_t count)
 {
        int ret;
        struct i2c_msg msg[2];
@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
+               printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
                return -EREMOTEIO;
        }
 
@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
                int i;
                dprintk("R(%d):", reg & 0x7f);
                for (i = 0; i < count; i++)
-                       printk(" %02x", ((const u8 *) buf)[i]);
+                       printk(" %02x", buf[i]);
                printk("\n");
        }
 
@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
 }
 
 static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
-                      const void *src, const size_t count)
+                      const u8 *src, const size_t count)
 {
        int ret;
        u8 buf[count + 1];
@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
                int i;
                dprintk("W(%d):", reg & 0x7f);
                for (i = 0; i < count; i++)
-                       printk(" %02x", ((const u8 *) src)[i]);
+                       printk(" %02x", src[i]);
                printk("\n");
        }
 
@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
        ret = i2c_transfer(state->i2c, &msg, 1);
 
        if (ret != 1) {
-               dprintk("%s: ret == %d\n", __FUNCTION__, ret);
+               dprintk("%s: ret == %d\n", __func__, ret);
                return -EREMOTEIO;
        }
 
@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
                dprintk("sym_rat_op=%d dec_ratio=%d\n",
                       sym_rat_op, dec_ratio);
                dprintk("*sr(manual) = %lu\n",
-                      (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
+                      (((state->xtal * 8192) / (sym_rat_op + 8192)) *
                        2) - dec_ratio);
        }
 
@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
 
        /* wake up */
        ret = mt312_writereg(state, CONFIG,
-                       (state->frequency == 60 ? 0x88 : 0x8c));
+                       (state->freq_mult == 6 ? 0x88 : 0x8c));
        if (ret < 0)
                return ret;
 
@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
                        return ret;
        }
 
+       switch (state->id) {
+       case ID_ZL10313:
+               /* enable ADC */
+               ret = mt312_writereg(state, GPP_CTRL, 0x80);
+               if (ret < 0)
+                       return ret;
+
+               /* configure ZL10313 for optimal ADC performance */
+               buf[0] = 0x80;
+               buf[1] = 0xB0;
+               ret = mt312_write(state, HW_CTRL, buf, 2);
+               if (ret < 0)
+                       return ret;
+
+               /* enable MPEG output and ADCs */
+               ret = mt312_writereg(state, HW_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               ret = mt312_writereg(state, MPEG_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               break;
+       }
+
        /* SYS_CLK */
-       buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
-                               MT312_SYS_CLK) * 2, 1000000);
+       buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
 
        /* DISEQC_RATIO */
-       buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
+       buf[1] = mt312_div(state->xtal, 22000 * 4);
 
        ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
        if (ret < 0)
@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
        if (ret < 0)
                return ret;
 
-       ret = mt312_writereg(state, OP_CTRL, 0x53);
+       /* different MOCLK polarity */
+       switch (state->id) {
+       case ID_ZL10313:
+               buf[0] = 0x33;
+               break;
+       default:
+               buf[0] = 0x53;
+               break;
+       }
+
+       ret = mt312_writereg(state, OP_CTRL, buf[0]);
        if (ret < 0)
                return ret;
 
@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
        if (ret < 0)
                return ret;
 
+       /* is there a better way to wait for message to be transmitted */
+       msleep(100);
+
        /* set DISEQC_MODE[2:0] to zero if a return message is expected */
        if (c->msg[0] & 0x02) {
                ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
 {
        struct mt312_state *state = fe->demodulator_priv;
        const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
+       u8 val;
 
        if (v > SEC_VOLTAGE_OFF)
                return -EINVAL;
 
-       return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
+       val = volt_tab[v];
+       if (state->config->voltage_inverted)
+               val ^= 0x40;
+
+       return mt312_writereg(state, DISEQC_MODE, val);
 }
 
 static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
        int ret;
        u8 buf[2];
 
-       ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
+       ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
        int ret;
        u8 buf[2];
 
-       ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
+       ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
            { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
        const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
 
-       dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
+       dprintk("%s: Freq %d\n", __func__, p->frequency);
 
        if ((p->frequency < fe->ops.info.frequency_min)
            || (p->frequency > fe->ops.info.frequency_max))
@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
                        return ret;
                if (p->u.qpsk.symbol_rate >= 30000000) {
                        /* Note that 30MS/s should use 90MHz */
-                       if ((config_val & 0x0c) == 0x08) {
+                       if (state->freq_mult == 6) {
                                /* We are running 60MHz */
-                               state->frequency = 90;
+                               state->freq_mult = 9;
                                ret = mt312_initfe(fe);
                                if (ret < 0)
                                        return ret;
                        }
                } else {
-                       if ((config_val & 0x0c) == 0x0C) {
+                       if (state->freq_mult == 9) {
                                /* We are running 90MHz */
-                               state->frequency = 60;
+                               state->freq_mult = 6;
                                ret = mt312_initfe(fe);
                                if (ret < 0)
                                        return ret;
@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
                break;
 
        case ID_MT312:
+       case ID_ZL10313:
                break;
 
        default:
@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct mt312_state *state = fe->demodulator_priv;
 
-       if (enable) {
-               return mt312_writereg(state, GPP_CTRL, 0x40);
-       } else {
-               return mt312_writereg(state, GPP_CTRL, 0x00);
+       u8 val = 0x00;
+       int ret;
+
+       switch (state->id) {
+       case ID_ZL10313:
+               ret = mt312_readreg(state, GPP_CTRL, &val);
+               if (ret < 0)
+                       goto error;
+
+               /* preserve this bit to not accidently shutdown ADC */
+               val &= 0x80;
+               break;
        }
+
+       if (enable)
+               val |= 0x40;
+       else
+               val &= ~0x40;
+
+       ret = mt312_writereg(state, GPP_CTRL, val);
+
+error:
+       return ret;
 }
 
 static int mt312_sleep(struct dvb_frontend *fe)
@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
        if (ret < 0)
                return ret;
 
+       if (state->id == ID_ZL10313) {
+               /* reset ADC */
+               ret = mt312_writereg(state, GPP_CTRL, 0x00);
+               if (ret < 0)
+                       return ret;
+
+               /* full shutdown of ADCs, mpeg bus tristated */
+               ret = mt312_writereg(state, HW_CTRL, 0x0d);
+               if (ret < 0)
+                       return ret;
+       }
+
        ret = mt312_readreg(state, CONFIG, &config);
        if (ret < 0)
                return ret;
@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe)
        kfree(state);
 }
 
+#define MT312_SYS_CLK          90000000UL      /* 90 MHz */
 static struct dvb_frontend_ops vp310_mt312_ops = {
 
        .info = {
@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
                .type = FE_QPSK,
                .frequency_min = 950000,
                .frequency_max = 2150000,
-               .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
-               .symbol_rate_min = MT312_SYS_CLK / 128,
+               .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
+               .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
                .symbol_rate_max = MT312_SYS_CLK / 2,
                .caps =
                    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
        switch (state->id) {
        case ID_VP310:
                strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
-               state->frequency = 90;
+               state->xtal = MT312_PLL_CLK;
+               state->freq_mult = 9;
                break;
        case ID_MT312:
                strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
-               state->frequency = 60;
+               state->xtal = MT312_PLL_CLK;
+               state->freq_mult = 6;
+               break;
+       case ID_ZL10313:
+               strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+               state->xtal = MT312_PLL_CLK_10_111;
+               state->freq_mult = 9;
                break;
        default:
-               printk(KERN_WARNING "Only Zarlink VP310/MT312"
+               printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
                        " are supported chips.\n");
                goto error;
        }
@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
 MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
index f17cb93ba9ba068e8a486cd804176b3e96a02a1d..96338f0c4dd47268d60727b9a35b251d62b469ad 100644 (file)
@@ -31,6 +31,9 @@
 struct mt312_config {
        /* the demodulator's i2c address */
        u8 demod_address;
+
+       /* inverted voltage setting */
+       int voltage_inverted:1;
 };
 
 #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
@@ -40,7 +43,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
 static inline struct dvb_frontend *vp310_mt312_attach(
        const struct mt312_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_MT312 */
index 5e0b95b5337bc8be7d91903bbe0581131371380e..a3959f94d6398b0694d5df1d5f0edd0bedddc291 100644 (file)
@@ -110,6 +110,8 @@ enum mt312_reg_addr {
        VIT_ERRPER_H = 83,
        VIT_ERRPER_M = 84,
        VIT_ERRPER_L = 85,
+       HW_CTRL = 84,   /* ZL10313 only */
+       MPEG_CTRL = 85, /* ZL10313 only */
        VIT_SETUP = 86,
        VIT_REF0 = 87,
        VIT_REF1 = 88,
@@ -156,7 +158,8 @@ enum mt312_reg_addr {
 
 enum mt312_model_id {
        ID_VP310 = 1,
-       ID_MT312 = 3
+       ID_MT312 = 3,
+       ID_ZL10313 = 5,
 };
 
 #endif                         /* DVB_FRONTENDS_MT312_PRIV */
index 7cd190b6f01573919e7939948b8f922e8f5622b2..beba5aa0db5000e17d520ef8e473953c8720662d 100644 (file)
@@ -95,7 +95,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
 
        if (ret != 2) {
                printk("%s: readreg error (reg=%d, ret==%i)\n",
-                      __FUNCTION__, reg, ret);
+                      __func__, reg, ret);
                return ret;
        }
 
@@ -135,7 +135,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
        value = 64 * bw * (1<<16) / (7 * 8);
        value = value * 1000 / adc_clock;
        dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-               __FUNCTION__, bw, adc_clock, value);
+               __func__, bw, adc_clock, value);
        buf[0] = msb(value);
        buf[1] = lsb(value);
 }
@@ -161,7 +161,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
        }
        value = -16374 * ife / adc_clock;
        dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-               __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
+               __func__, if2, ife, adc_clock, value, value & 0x3fff);
        buf[0] = msb(value);
        buf[1] = lsb(value);
 }
@@ -521,7 +521,7 @@ static int mt352_init(struct dvb_frontend* fe)
 
        static u8 mt352_reset_attach [] = { RESET, 0xC0 };
 
-       dprintk("%s: hello\n",__FUNCTION__);
+       dprintk("%s: hello\n",__func__);
 
        if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
            (mt352_read_register(state, CONFIG) & 0x20) == 0) {
index e9964081fd8436cc48397fd6e1cde634fe764896..595092f9f0c4a7caf1a73f5b623d21234c33eca1 100644 (file)
@@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
 static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
                                         struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_MT352
index fcf964fe1d6bebb2ca9f62847fdcfd67ee8d05b1..23d022852543a1a3c9dfd7a0fdc2f2eb35799b5a 100644 (file)
@@ -74,7 +74,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, addr, err);
+                       __func__, addr, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -87,7 +87,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, addr, err);
+                       __func__, addr, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -104,7 +104,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -121,7 +121,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le
 
        if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
                printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
        return 0;
@@ -146,7 +146,7 @@ static u16 nxt200x_crc(u16 crc, u8 c)
 static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
 {
        u8 attr, len2, buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set mutli register register */
        nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -207,7 +207,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
 {
        int i;
        u8 buf, len2, attr;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set mutli register register */
        nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -254,7 +254,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
 static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
 {
        u8 buf, stopval, counter = 0;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* set correct stop value */
        switch (state->demod_chip) {
@@ -287,7 +287,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
 static void nxt200x_microcontroller_start (struct nxt200x_state* state)
 {
        u8 buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        buf = 0x00;
        nxt200x_writebytes(state, 0x22, &buf, 1);
@@ -297,7 +297,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
 {
        u8 buf[9];
        u8 counter = 0;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        buf[0] = 0x00;
        nxt200x_writebytes(state, 0x2b, buf, 1);
@@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 {
        u8 buf, count = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
 
@@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 static void nxt200x_agc_reset(struct nxt200x_state* state)
 {
        u8 buf;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (state->demod_chip) {
                case NXT2002:
@@ -416,7 +416,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
        u8 buf[3], written = 0, chunkpos = 0;
        u16 rambase, position, crc = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        dprintk("Firmware is %zu bytes\n", fw->size);
 
        /* Get the RAM base for this nxt2002 */
@@ -483,7 +483,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
        u8 buf[3];
        u16 rambase, position, crc=0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        dprintk("Firmware is %zu bytes\n", fw->size);
 
        /* set rambase */
index bb0ef58d797277dbdc93c70bcc9c873ba4efd214..f3c84583770f80a1e5f5e3fabdacf29bdc7c400c 100644 (file)
@@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
 static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_NXT200X
index d313d7dcf3862c6fa67e1a0b6e0cd33a9c386277..0eef22dbf8a041ae5f82e0aecc5cc36770ab1d0a 100644 (file)
@@ -38,7 +38,7 @@ struct nxt6000_state {
        struct dvb_frontend frontend;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk if (debug) printk
 
 static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
index 13d22518356ed1c06f8f28206e9ff1ceb5516081..878eb38a075ecbfff4c572caf5a52557f6876881 100644 (file)
@@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
 static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_NXT6000
index 8ffb8daca0313b53f54a9208e5cb467daa6c10f8..c7b5785f81f263321c83d54e93a26d51348ad333 100644 (file)
@@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
                *status = 0;
                return -EREMOTEIO;
        }
-       dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
+       dprintk("%s: read_status %04x\n", __func__, reg);
 
        if (reg & 0x0100) /* Receiver Lock */
                *status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
@@ -504,14 +504,14 @@ start:
                if (retry--) goto start;
                return -EREMOTEIO;
        }
-       dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
+       dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
                reg&0xff, reg&0x1000?"n":"ff");
 
        /* Calculate SNR using noise, c, and NTSC rejection correction */
        state->snr = calculate_snr(noise, c) - usK;
        *snr = (state->snr) >> 16;
 
-       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+       dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
index add24f0a743b9cbb9326b032b42582d233eceb37..1b8e04d973c8c8ec41036befdef092404c2028b0 100644 (file)
@@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
 static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_OR51132
index 6a6b0d727c6fc53ece47c2816086e8cf9025cf3f..7eaa4765593f039dc82c4983baeac5dedfeb787f 100644 (file)
@@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
 
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
                printk(KERN_WARNING "%s: error writing snr reg\n",
-                      __FUNCTION__);
+                      __func__);
                return -1;
        }
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
                printk(KERN_WARNING "%s: read_status read error\n",
-                      __FUNCTION__);
+                      __func__);
                return -1;
        }
 
        state->snr = calculate_snr(rec_buf[0], 89599047);
        *snr = (state->snr) >> 16;
 
-       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
+       dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
 
        return 0;
index 8aad8402d615d45aea6de0d7edb72e818ad66143..3ce0508b898e102b1cf13ee8e18915e2b783b515 100644 (file)
@@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
 static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_OR51211
index 3ab4aa045c36891fccb7aec871dce427cf112bd8..cff6a7ca53801cce4335b41a24c8f29f7cf93a0a 100644 (file)
@@ -45,7 +45,7 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
                                                 struct i2c_adapter *i2c,
                                                 struct qt1010_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_QT1010
index 1a4d8319773c73ffd8a858ca4c150c2f58df9d97..b999ec424ff7782041bc2c8fcb993a7355ec04dc 100644 (file)
@@ -48,7 +48,7 @@ struct s5h1409_state {
        u32 qam_state;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 /* Register values to initialise the demod, this will set VSB by default */
@@ -312,7 +312,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
 
        if (ret != 1)
                printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-                      "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                      "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -332,7 +332,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2)
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
        return (b1[0] << 8) | b1[1];
 }
 
@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        s5h1409_writereg(state, 0xf5, 0);
        s5h1409_writereg(state, 0xf5, 1);
@@ -356,7 +356,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
+       dprintk("%s(%d KHz)\n", __func__, KHz);
 
        switch (KHz) {
        case 4000:
@@ -381,7 +381,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, inverted);
+       dprintk("%s(%d)\n", __func__, inverted);
 
        if(inverted == 1)
                return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
@@ -394,25 +394,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(0x%08x)\n", __FUNCTION__, m);
+       dprintk("%s(0x%08x)\n", __func__, m);
 
        switch(m) {
        case VSB_8:
-               dprintk("%s() VSB_8\n", __FUNCTION__);
+               dprintk("%s() VSB_8\n", __func__);
                if (state->if_freq != S5H1409_VSB_IF_FREQ)
                        s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
                s5h1409_writereg(state, 0xf4, 0);
                break;
        case QAM_64:
        case QAM_256:
-               dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
+               dprintk("%s() QAM_AUTO (64/256)\n", __func__);
                if (state->if_freq != S5H1409_QAM_IF_FREQ)
                        s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
                s5h1409_writereg(state, 0xf4, 1);
                s5h1409_writereg(state, 0x85, 0x110);
                break;
        default:
-               dprintk("%s() Invalid modulation\n", __FUNCTION__);
+               dprintk("%s() Invalid modulation\n", __func__);
                return -EINVAL;
        }
 
@@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        if (enable)
                return s5h1409_writereg(state, 0xf3, 1);
@@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        if (enable)
                return s5h1409_writereg(state, 0xe3,
@@ -452,7 +452,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(%d)\n", __FUNCTION__, enable);
+       dprintk("%s(%d)\n", __func__, enable);
 
        return s5h1409_writereg(state, 0xf2, enable);
 }
@@ -461,7 +461,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        return s5h1409_writereg(state, 0xfa, 0);
 }
@@ -534,7 +534,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
 {
        struct s5h1409_state* state = fe->demodulator_priv;
 
-       dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
+       dprintk("%s(frequency=%d)\n", __func__, p->frequency);
 
        s5h1409_softreset(fe);
 
@@ -565,7 +565,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
        struct s5h1409_state *state = fe->demodulator_priv;
        u16 val;
 
-       dprintk("%s(%d)\n", __FUNCTION__, mode);
+       dprintk("%s(%d)\n", __func__, mode);
 
        val = s5h1409_readreg(state, 0xac) & 0xcfff;
        switch (mode) {
@@ -573,7 +573,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
                val |= 0x0000;
                break;
        case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
-               dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
+               dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
                val |= 0x1000;
                break;
        case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
@@ -597,7 +597,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
        int i;
 
        struct s5h1409_state* state = fe->demodulator_priv;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        s5h1409_sleep(fe, 0);
        s5h1409_register_reset(fe);
@@ -663,7 +663,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
                break;
        }
 
-       dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
+       dprintk("%s() status 0x%08x\n", __func__, *status);
 
        return 0;
 }
@@ -671,7 +671,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
 static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
                if (v < qam256_snr_tab[i].val) {
@@ -686,7 +686,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
                if (v < qam64_snr_tab[i].val) {
@@ -701,7 +701,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
 {
        int i, ret = -EINVAL;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
                if (v > vsb_snr_tab[i].val) {
@@ -710,7 +710,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
                        break;
                }
        }
-       dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
+       dprintk("%s() snr=%d\n", __func__, *snr);
        return ret;
 }
 
@@ -718,7 +718,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct s5h1409_state* state = fe->demodulator_priv;
        u16 reg;
-       dprintk("%s()\n", __FUNCTION__);
+       dprintk("%s()\n", __func__);
 
        switch(state->current_modulation) {
        case QAM_64:
@@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
 
        if (s5h1409_init(&state->frontend) != 0) {
                printk(KERN_ERR "%s: Failed to initialize correctly\n",
-                       __FUNCTION__);
+                       __func__);
                goto error;
        }
 
index f0bb13fe808b99053333be93699d7eefb74c118a..59f4335964c6625a78ccba31e2db6ce24855466c 100644 (file)
@@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
 static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
                                                  struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_S5H1409 */
index 2c2c344c4c648a3c85c92f3c7e6f8f4a98e85594..281e1cb2edc67d516361a4114b8864a7c3c716b6 100644 (file)
@@ -1,24 +1,26 @@
 /*
-Driver for Samsung S5H1420 QPSK Demodulator
-
-Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #include <linux/jiffies.h>
 #include <asm/div64.h>
 
-#include "dvb_frontend.h"
-#include "s5h1420.h"
+#include <linux/i2c.h>
 
 
+#include "dvb_frontend.h"
+#include "s5h1420.h"
+#include "s5h1420_priv.h"
 
 #define TONE_FREQ 22000
 
 struct s5h1420_state {
        struct i2c_adapter* i2c;
        const struct s5h1420_config* config;
+
        struct dvb_frontend frontend;
+       struct i2c_adapter tuner_i2c_adapter;
+
+       u8 CON_1_val;
 
        u8 postlocked:1;
        u32 fclk;
        u32 tunedfreq;
        fe_code_rate_t fec_inner;
        u32 symbol_rate;
+
+       /* FIXME: ugly workaround for flexcop's incapable i2c-controller
+        * it does not support repeated-start, workaround: write addr-1
+        * and then read
+        */
+       u8 shadow[255];
 };
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
@@ -53,44 +67,66 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
                                     struct dvb_frontend_tune_settings* fesettings);
 
 
-static int debug = 0;
-#define dprintk if (debug) printk
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debugging");
+
+#define dprintk(x...) do { \
+       if (debug) \
+               printk(KERN_DEBUG "S5H1420: " x); \
+} while (0)
+
+static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
+{
+       int ret;
+       u8 b[2];
+       struct i2c_msg msg[] = {
+               { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
+               { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
+       };
+
+       b[0] = (reg - 1) & 0xff;
+       b[1] = state->shadow[(reg - 1) & 0xff];
+
+       if (state->config->repeated_start_workaround) {
+               ret = i2c_transfer(state->i2c, msg, 3);
+               if (ret != 3)
+                       return ret;
+       } else {
+               ret = i2c_transfer(state->i2c, &msg[1], 2);
+               if (ret != 2)
+                       return ret;
+       }
+
+       /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
+
+       return b[0];
+}
 
 static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
 {
-       u8 buf [] = { reg, data };
+       u8 buf[] = { reg, data };
        struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
        int err;
 
-       if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+       /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
+       err = i2c_transfer(state->i2c, &msg, 1);
+       if (err != 1) {
+               dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
+       state->shadow[reg] = data;
 
        return 0;
 }
 
-static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
-{
-       int ret;
-       u8 b0 [] = { reg };
-       u8 b1 [] = { 0 };
-       struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
-       struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
-
-       if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
-               return ret;
-
-       if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
-               return ret;
-
-       return b1[0];
-}
-
 static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
+       dprintk("enter %s\n", __func__);
+
        switch(voltage) {
        case SEC_VOLTAGE_13:
                s5h1420_writereg(state, 0x3c,
@@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
                break;
        }
 
+       dprintk("leave %s\n", __func__);
        return 0;
 }
 
@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
+       dprintk("enter %s\n", __func__);
        switch(tone) {
        case SEC_TONE_ON:
                s5h1420_writereg(state, 0x3b,
@@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
                                 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
                break;
        }
+       dprintk("leave %s\n", __func__);
 
        return 0;
 }
@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
        unsigned long timeout;
        int result = 0;
 
+       dprintk("enter %s\n", __func__);
        if (cmd->msg_len > 8)
                return -EINVAL;
 
@@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
        /* restore original settings */
        s5h1420_writereg(state, 0x3b, val);
        msleep(15);
+       dprintk("leave %s\n", __func__);
        return result;
 }
 
@@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
        struct s5h1420_state* state = fe->demodulator_priv;
        u8 val;
 
+       dprintk("enter %s\n", __func__);
+
        if (status == NULL)
                return -EINVAL;
 
@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
        the inversion, wait a bit and check again */
-       if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
-               val = s5h1420_readreg(state, 0x32);
+       if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
+               val = s5h1420_readreg(state, Vit10);
                if ((val & 0x07) == 0x03) {
                        if (val & 0x08)
-                               s5h1420_writereg(state, 0x31, 0x13);
+                               s5h1420_writereg(state, Vit09, 0x13);
                        else
-                               s5h1420_writereg(state, 0x31, 0x1b);
+                               s5h1420_writereg(state, Vit09, 0x1b);
 
                        /* wait a bit then update lock status */
                        mdelay(200);
@@ -312,68 +355,73 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
        }
 
        /* perform post lock setup */
-       if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
+       if ((*status & FE_HAS_LOCK) && !state->postlocked) {
 
                /* calculate the data rate */
                u32 tmp = s5h1420_getsymbolrate(state);
-               switch(s5h1420_readreg(state, 0x32) & 0x07) {
-               case 0:
-                       tmp = (tmp * 2 * 1) / 2;
-                       break;
-
-               case 1:
-                       tmp = (tmp * 2 * 2) / 3;
-                       break;
-
-               case 2:
-                       tmp = (tmp * 2 * 3) / 4;
-                       break;
-
-               case 3:
-                       tmp = (tmp * 2 * 5) / 6;
-                       break;
-
-               case 4:
-                       tmp = (tmp * 2 * 6) / 7;
-                       break;
-
-               case 5:
-                       tmp = (tmp * 2 * 7) / 8;
-                       break;
+               switch (s5h1420_readreg(state, Vit10) & 0x07) {
+               case 0: tmp = (tmp * 2 * 1) / 2; break;
+               case 1: tmp = (tmp * 2 * 2) / 3; break;
+               case 2: tmp = (tmp * 2 * 3) / 4; break;
+               case 3: tmp = (tmp * 2 * 5) / 6; break;
+               case 4: tmp = (tmp * 2 * 6) / 7; break;
+               case 5: tmp = (tmp * 2 * 7) / 8; break;
                }
+
                if (tmp == 0) {
-                       printk("s5h1420: avoided division by 0\n");
+                       printk(KERN_ERR "s5h1420: avoided division by 0\n");
                        tmp = 1;
                }
                tmp = state->fclk / tmp;
 
+
                /* set the MPEG_CLK_INTL for the calculated data rate */
-               if (tmp < 4)
+               if (tmp < 2)
                        val = 0x00;
-               else if (tmp < 8)
+               else if (tmp < 5)
                        val = 0x01;
-               else if (tmp < 12)
+               else if (tmp < 9)
                        val = 0x02;
-               else if (tmp < 16)
+               else if (tmp < 13)
                        val = 0x03;
-               else if (tmp < 24)
+               else if (tmp < 17)
                        val = 0x04;
-               else if (tmp < 32)
+               else if (tmp < 25)
                        val = 0x05;
-               else
+               else if (tmp < 33)
                        val = 0x06;
-               s5h1420_writereg(state, 0x22, val);
+               else
+                       val = 0x07;
+               dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
+
+               s5h1420_writereg(state, FEC01, 0x18);
+               s5h1420_writereg(state, FEC01, 0x10);
+               s5h1420_writereg(state, FEC01, val);
+
+               /* Enable "MPEG_Out" */
+               val = s5h1420_readreg(state, Mpeg02);
+               s5h1420_writereg(state, Mpeg02, val | (1 << 6));
 
-               /* DC freeze */
-               s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
+               /* kicker disable */
+               val = s5h1420_readreg(state, QPSK01) & 0x7f;
+               s5h1420_writereg(state, QPSK01, val);
 
-               /* kicker disable + remove DC offset */
-               s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
+               /* DC freeze TODO it was never activated by default or it can stay activated */
+
+               if (s5h1420_getsymbolrate(state) >= 20000000) {
+                       s5h1420_writereg(state, Loop04, 0x8a);
+                       s5h1420_writereg(state, Loop05, 0x6a);
+               } else {
+                       s5h1420_writereg(state, Loop04, 0x58);
+                       s5h1420_writereg(state, Loop05, 0x27);
+               }
 
                /* post-lock processing has been done! */
                state->postlocked = 1;
        }
 
+       dprintk("leave %s\n", __func__);
+
        return 0;
 }
 
@@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 
 static void s5h1420_reset(struct s5h1420_state* state)
 {
+       dprintk("%s\n", __func__);
        s5h1420_writereg (state, 0x01, 0x08);
        s5h1420_writereg (state, 0x01, 0x00);
        udelay(10);
@@ -422,54 +471,52 @@ static void s5h1420_reset(struct s5h1420_state* state)
 static void s5h1420_setsymbolrate(struct s5h1420_state* state,
                                  struct dvb_frontend_parameters *p)
 {
+       u8 v;
        u64 val;
 
+       dprintk("enter %s\n", __func__);
+
        val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
-       if (p->u.qpsk.symbol_rate <= 21000000) {
+       if (p->u.qpsk.symbol_rate < 29000000)
                val *= 2;
-       }
        do_div(val, (state->fclk / 1000));
 
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
-       s5h1420_writereg(state, 0x11, val >> 16);
-       s5h1420_writereg(state, 0x12, val >> 8);
-       s5h1420_writereg(state, 0x13, val & 0xff);
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
+       dprintk("symbol rate register: %06llx\n", val);
+
+       v = s5h1420_readreg(state, Loop01);
+       s5h1420_writereg(state, Loop01, v & 0x7f);
+       s5h1420_writereg(state, Tnco01, val >> 16);
+       s5h1420_writereg(state, Tnco02, val >> 8);
+       s5h1420_writereg(state, Tnco03, val & 0xff);
+       s5h1420_writereg(state, Loop01,  v | 0x80);
+       dprintk("leave %s\n", __func__);
 }
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
 {
-       u64 val = 0;
-       int sampling = 2;
-
-       if (s5h1420_readreg(state, 0x05) & 0x2)
-               sampling = 1;
-
-       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
-       val  = s5h1420_readreg(state, 0x11) << 16;
-       val |= s5h1420_readreg(state, 0x12) << 8;
-       val |= s5h1420_readreg(state, 0x13);
-       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
-
-       val *= (state->fclk / 1000ULL);
-       do_div(val, ((1<<24) * sampling));
-
-       return (u32) (val * 1000ULL);
+       return state->symbol_rate;
 }
 
 static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
 {
        int val;
+       u8 v;
+
+       dprintk("enter %s\n", __func__);
 
        /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
         * divide fclk by 1000000 to get the correct value. */
        val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
 
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
-       s5h1420_writereg(state, 0x0e, val >> 16);
-       s5h1420_writereg(state, 0x0f, val >> 8);
-       s5h1420_writereg(state, 0x10, val & 0xff);
-       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
+       dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
+
+       v = s5h1420_readreg(state, Loop01);
+       s5h1420_writereg(state, Loop01, v & 0xbf);
+       s5h1420_writereg(state, Pnco01, val >> 16);
+       s5h1420_writereg(state, Pnco02, val >> 8);
+       s5h1420_writereg(state, Pnco03, val & 0xff);
+       s5h1420_writereg(state, Loop01, v | 0x40);
+       dprintk("leave %s\n", __func__);
 }
 
 static int s5h1420_getfreqoffset(struct s5h1420_state* state)
@@ -496,52 +543,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
                                     struct dvb_frontend_parameters *p)
 {
        u8 inversion = 0;
+       u8 vit08, vit09;
+
+       dprintk("enter %s\n", __func__);
 
-       if (p->inversion == INVERSION_OFF) {
+       if (p->inversion == INVERSION_OFF)
                inversion = state->config->invert ? 0x08 : 0;
-       } else if (p->inversion == INVERSION_ON) {
+       else if (p->inversion == INVERSION_ON)
                inversion = state->config->invert ? 0 : 0x08;
-       }
 
        if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
-               s5h1420_writereg(state, 0x30, 0x3f);
-               s5h1420_writereg(state, 0x31, 0x00 | inversion);
+               vit08 = 0x3f;
+               vit09 = 0;
        } else {
                switch(p->u.qpsk.fec_inner) {
                case FEC_1_2:
-                       s5h1420_writereg(state, 0x30, 0x01);
-                       s5h1420_writereg(state, 0x31, 0x10 | inversion);
+                       vit08 = 0x01; vit09 = 0x10;
                        break;
 
                case FEC_2_3:
-                       s5h1420_writereg(state, 0x30, 0x02);
-                       s5h1420_writereg(state, 0x31, 0x11 | inversion);
+                       vit08 = 0x02; vit09 = 0x11;
                        break;
 
                case FEC_3_4:
-                       s5h1420_writereg(state, 0x30, 0x04);
-                       s5h1420_writereg(state, 0x31, 0x12 | inversion);
+                       vit08 = 0x04; vit09 = 0x12;
                        break;
 
                case FEC_5_6:
-                       s5h1420_writereg(state, 0x30, 0x08);
-                       s5h1420_writereg(state, 0x31, 0x13 | inversion);
+                       vit08 = 0x08; vit09 = 0x13;
                        break;
 
                case FEC_6_7:
-                       s5h1420_writereg(state, 0x30, 0x10);
-                       s5h1420_writereg(state, 0x31, 0x14 | inversion);
+                       vit08 = 0x10; vit09 = 0x14;
                        break;
 
                case FEC_7_8:
-                       s5h1420_writereg(state, 0x30, 0x20);
-                       s5h1420_writereg(state, 0x31, 0x15 | inversion);
+                       vit08 = 0x20; vit09 = 0x15;
                        break;
 
                default:
                        return;
                }
        }
+       vit09 |= inversion;
+       dprintk("fec: %02x %02x\n", vit08, vit09);
+       s5h1420_writereg(state, Vit08, vit08);
+       s5h1420_writereg(state, Vit09, vit09);
+       dprintk("leave %s\n", __func__);
 }
 
 static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
@@ -583,16 +631,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        struct s5h1420_state* state = fe->demodulator_priv;
        int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
+       uint8_t clock_settting;
+
+       dprintk("enter %s\n", __func__);
 
        /* check if we should do a fast-tune */
        memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
        s5h1420_get_tune_settings(fe, &fesettings);
        frequency_delta = p->frequency - state->tunedfreq;
        if ((frequency_delta > -fesettings.max_drift) &&
-           (frequency_delta < fesettings.max_drift) &&
-           (frequency_delta != 0) &&
-           (state->fec_inner == p->u.qpsk.fec_inner) &&
-           (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+                       (frequency_delta < fesettings.max_drift) &&
+                       (frequency_delta != 0) &&
+                       (state->fec_inner == p->u.qpsk.fec_inner) &&
+                       (state->symbol_rate == p->u.qpsk.symbol_rate)) {
 
                if (fe->ops.tuner_ops.set_params) {
                        fe->ops.tuner_ops.set_params(fe, p);
@@ -606,54 +657,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
                } else {
                        s5h1420_setfreqoffset(state, 0);
                }
+               dprintk("simple tune\n");
                return 0;
        }
+       dprintk("tuning demod\n");
 
        /* first of all, software reset */
        s5h1420_reset(state);
 
        /* set s5h1420 fclk PLL according to desired symbol rate */
-       if (p->u.qpsk.symbol_rate > 28000000) {
-               state->fclk = 88000000;
-               s5h1420_writereg(state, 0x03, 0x50);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xae);
-       } else if (p->u.qpsk.symbol_rate > 21000000) {
+       if (p->u.qpsk.symbol_rate > 33000000)
+               state->fclk = 80000000;
+       else if (p->u.qpsk.symbol_rate > 28500000)
                state->fclk = 59000000;
-               s5h1420_writereg(state, 0x03, 0x33);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xae);
-       } else {
+       else if (p->u.qpsk.symbol_rate > 25000000)
+               state->fclk = 86000000;
+       else if (p->u.qpsk.symbol_rate > 1900000)
                state->fclk = 88000000;
-               s5h1420_writereg(state, 0x03, 0x50);
-               s5h1420_writereg(state, 0x04, 0x40);
-               s5h1420_writereg(state, 0x05, 0xac);
+       else
+               state->fclk = 44000000;
+
+       /* Clock */
+       switch (state->fclk) {
+       default:
+       case 88000000:
+               clock_settting = 80;
+               break;
+       case 86000000:
+               clock_settting = 78;
+               break;
+       case 80000000:
+               clock_settting = 72;
+               break;
+       case 59000000:
+               clock_settting = 51;
+               break;
+       case 44000000:
+               clock_settting = 36;
+               break;
        }
+       dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+       s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
+       s5h1420_writereg(state, PLL02, 0x40);
+       s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
 
-       /* set misc registers */
-       s5h1420_writereg(state, 0x02, 0x00);
-       s5h1420_writereg(state, 0x06, 0x00);
-       s5h1420_writereg(state, 0x07, 0xb0);
-       s5h1420_writereg(state, 0x0a, 0xe7);
-       s5h1420_writereg(state, 0x0b, 0x78);
-       s5h1420_writereg(state, 0x0c, 0x48);
-       s5h1420_writereg(state, 0x0d, 0x6b);
-       s5h1420_writereg(state, 0x2e, 0x8e);
-       s5h1420_writereg(state, 0x35, 0x33);
-       s5h1420_writereg(state, 0x38, 0x01);
-       s5h1420_writereg(state, 0x39, 0x7d);
-       s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
-       s5h1420_writereg(state, 0x3c, 0x00);
-       s5h1420_writereg(state, 0x45, 0x61);
-       s5h1420_writereg(state, 0x46, 0x1d);
+       /* TODO DC offset removal, config parameter ? */
+       if (p->u.qpsk.symbol_rate > 29000000)
+               s5h1420_writereg(state, QPSK01, 0xae | 0x10);
+       else
+               s5h1420_writereg(state, QPSK01, 0xac | 0x10);
 
-       /* start QPSK */
-       s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
+       /* set misc registers */
+       s5h1420_writereg(state, CON_1, 0x00);
+       s5h1420_writereg(state, QPSK02, 0x00);
+       s5h1420_writereg(state, Pre01, 0xb0);
+
+       s5h1420_writereg(state, Loop01, 0xF0);
+       s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
+       s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
+       if (p->u.qpsk.symbol_rate > 20000000)
+               s5h1420_writereg(state, Loop04, 0x79);
+       else
+               s5h1420_writereg(state, Loop04, 0x58);
+       s5h1420_writereg(state, Loop05, 0x6b);
+
+       if (p->u.qpsk.symbol_rate >= 8000000)
+               s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
+       else if (p->u.qpsk.symbol_rate >= 4000000)
+               s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
+       else
+               s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
+
+       s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
+
+       s5h1420_writereg(state, Sync01, 0x33);
+       s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
+       s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
+       s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
+
+       s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
+       s5h1420_writereg(state, DiS03, 0x00);
+       s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
 
        /* set tuner PLL */
        if (fe->ops.tuner_ops.set_params) {
                fe->ops.tuner_ops.set_params(fe, p);
-               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
                s5h1420_setfreqoffset(state, 0);
        }
 
@@ -661,10 +751,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        s5h1420_setsymbolrate(state, p);
        s5h1420_setfec_inversion(state, p);
 
+       /* start QPSK */
+       s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
+
        state->fec_inner = p->u.qpsk.fec_inner;
        state->symbol_rate = p->u.qpsk.symbol_rate;
        state->postlocked = 0;
        state->tunedfreq = p->frequency;
+
+       dprintk("leave %s\n", __func__);
        return 0;
 }
 
@@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
-       if (enable) {
-               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-       } else {
-               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
-       }
+       if (enable)
+               return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
+       else
+               return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
 }
 
 static int s5h1420_init (struct dvb_frontend* fe)
@@ -729,7 +823,8 @@ static int s5h1420_init (struct dvb_frontend* fe)
        struct s5h1420_state* state = fe->demodulator_priv;
 
        /* disable power down and do reset */
-       s5h1420_writereg(state, 0x02, 0x10);
+       state->CON_1_val = 0x10;
+       s5h1420_writereg(state, 0x02, state->CON_1_val);
        msleep(10);
        s5h1420_reset(state);
 
@@ -739,26 +834,60 @@ static int s5h1420_init (struct dvb_frontend* fe)
 static int s5h1420_sleep(struct dvb_frontend* fe)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
-
-       return s5h1420_writereg(state, 0x02, 0x12);
+       state->CON_1_val = 0x12;
+       return s5h1420_writereg(state, 0x02, state->CON_1_val);
 }
 
 static void s5h1420_release(struct dvb_frontend* fe)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
+       i2c_del_adapter(&state->tuner_i2c_adapter);
        kfree(state);
 }
 
-static struct dvb_frontend_ops s5h1420_ops;
+static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+       struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
+       struct i2c_msg m[1 + num];
+       u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
+
+       memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
+
+       m[0].addr = state->config->demod_address;
+       m[0].buf  = tx_open;
+       m[0].len  = 2;
 
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-                                   struct i2c_adapter* i2c)
+       memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+       return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
+       .master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
+       .functionality = s5h1420_tuner_i2c_func,
+};
+
+struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       struct s5h1420_state* state = NULL;
-       u8 identity;
+       struct s5h1420_state *state = fe->demodulator_priv;
+       return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops s5h1420_ops;
 
+struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+                                   struct i2c_adapter *i2c)
+{
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+       struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+       u8 i;
+
        if (state == NULL)
                goto error;
 
@@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
        state->symbol_rate = 0;
 
        /* check if the demod is there + identify it */
-       identity = s5h1420_readreg(state, 0x00);
-       if (identity != 0x03)
+       i = s5h1420_readreg(state, ID01);
+       if (i != 0x03)
                goto error;
 
+       memset(state->shadow, 0xff, sizeof(state->shadow));
+
+       for (i = 0; i < 0x50; i++)
+               state->shadow[i] = s5h1420_readreg(state, i);
+
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
+
+       /* create tuner i2c adapter */
+       strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
+       state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
+       state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
+       state->tuner_i2c_adapter.algo_data = NULL;
+       i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+       if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+               printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
+               goto error;
+       }
+
        return &state->frontend;
 
 error:
        kfree(state);
        return NULL;
 }
+EXPORT_SYMBOL(s5h1420_attach);
 
 static struct dvb_frontend_ops s5h1420_ops = {
 
        .info = {
-               .name     = "Samsung S5H1420 DVB-S",
+               .name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
                .type     = FE_QPSK,
                .frequency_min    = 950000,
                .frequency_max    = 2150000,
@@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
        .set_voltage = s5h1420_set_voltage,
 };
 
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
-MODULE_AUTHOR("Andrew de Quincey");
+MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(s5h1420_attach);
index 1555870f7226b604ba6e9b2ef9e8eafdd82f26de..4c913f142bc4258a307fd38e63c1d488e97f72fb 100644 (file)
@@ -1,25 +1,26 @@
 /*
-    Driver for S5H1420 QPSK Demodulators
-
-    Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 #ifndef S5H1420_H
 #define S5H1420_H
 
@@ -31,17 +32,26 @@ struct s5h1420_config
        u8 demod_address;
 
        /* does the inversion require inversion? */
-       u8 invert:1;
+       u8 invert : 1;
+
+       u8 repeated_start_workaround : 1;
+       u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
 };
 
 #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-            struct i2c_adapter* i2c);
+extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+            struct i2c_adapter *i2c);
+extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
 #else
-static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
-                                          struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
        return NULL;
 }
 #endif // CONFIG_DVB_S5H1420
diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
new file mode 100644 (file)
index 0000000..d9c58d2
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
+ * Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef S5H1420_PRIV
+#define S5H1420_PRIV
+
+#include <asm/types.h>
+
+enum s5h1420_register {
+       ID01      = 0x00,
+       CON_0     = 0x01,
+       CON_1     = 0x02,
+       PLL01     = 0x03,
+       PLL02     = 0x04,
+       QPSK01    = 0x05,
+       QPSK02    = 0x06,
+       Pre01     = 0x07,
+       Post01    = 0x08,
+       Loop01    = 0x09,
+       Loop02    = 0x0a,
+       Loop03    = 0x0b,
+       Loop04    = 0x0c,
+       Loop05    = 0x0d,
+       Pnco01    = 0x0e,
+       Pnco02    = 0x0f,
+       Pnco03    = 0x10,
+       Tnco01    = 0x11,
+       Tnco02    = 0x12,
+       Tnco03    = 0x13,
+       Monitor01 = 0x14,
+       Monitor02 = 0x15,
+       Monitor03 = 0x16,
+       Monitor04 = 0x17,
+       Monitor05 = 0x18,
+       Monitor06 = 0x19,
+       Monitor07 = 0x1a,
+       Monitor12 = 0x1f,
+
+       FEC01     = 0x22,
+       Soft01    = 0x23,
+       Soft02    = 0x24,
+       Soft03    = 0x25,
+       Soft04    = 0x26,
+       Soft05    = 0x27,
+       Soft06    = 0x28,
+       Vit01     = 0x29,
+       Vit02     = 0x2a,
+       Vit03     = 0x2b,
+       Vit04     = 0x2c,
+       Vit05     = 0x2d,
+       Vit06     = 0x2e,
+       Vit07     = 0x2f,
+       Vit08     = 0x30,
+       Vit09     = 0x31,
+       Vit10     = 0x32,
+       Vit11     = 0x33,
+       Vit12     = 0x34,
+       Sync01    = 0x35,
+       Sync02    = 0x36,
+       Rs01      = 0x37,
+       Mpeg01    = 0x38,
+       Mpeg02    = 0x39,
+       DiS01     = 0x3a,
+       DiS02     = 0x3b,
+       DiS03     = 0x3c,
+       DiS04     = 0x3d,
+       DiS05     = 0x3e,
+       DiS06     = 0x3f,
+       DiS07     = 0x40,
+       DiS08     = 0x41,
+       DiS09     = 0x42,
+       DiS10     = 0x43,
+       DiS11     = 0x44,
+       Rf01      = 0x45,
+       Err01     = 0x46,
+       Err02     = 0x47,
+       Err03     = 0x48,
+       Err04     = 0x49,
+};
+
+
+#endif
index da876f7bfe32b045595a568297c77c3f79aed534..aa78aa14aad927564108b19afa05a74efdabd646 100644 (file)
@@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
        int err;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
        ret = i2c_transfer (state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
                return -1;
        }
 
@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
        int tx_len;
        int err = 0;
 
-       dprintk ("%s: ...\n", __FUNCTION__);
+       dprintk ("%s: ...\n", __func__);
 
        if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
                return -EINVAL;
@@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
                msg.buf = tx_buf;
                msg.len = tx_len + 2;
                if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-                       printk("%s: firmware upload failed!\n", __FUNCTION__);
-                       printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+                       printk("%s: firmware upload failed!\n", __func__);
+                       printk ("%s: i2c error (err == %i)\n", __func__, err);
                        return err;
                }
                fw_pos += tx_len;
        }
 
-       dprintk ("%s: done!\n", __FUNCTION__);
+       dprintk ("%s: done!\n", __func__);
        return 0;
 };
 
@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
        if (state->initialised) return 0;
        state->initialised = 1;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
 
        /* request the firmware, this will block until someone uploads it */
@@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks
        return 0;
 }
 
-// number of trials to recover from lockup
+/* number of trials to recover from lockup */
 #define MAXTRIALS 5
-// maximum checks for data valid signal
+/* maximum checks for data valid signal */
 #define MAXCHECKS 100
 
-// only for debugging: counter for detected lockups
-static int lockups = 0;
-// only for debugging: counter for channel switches
-static int switches = 0;
+/* only for debugging: counter for detected lockups */
+static int lockups;
+/* only for debugging: counter for channel switches */
+static int switches;
 
 static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
        int trials = 0;
        int check_count = 0;
 
-       dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
+       dprintk("%s: frequency = %i\n", __func__, p->frequency);
 
        for (trials = 1; trials <= MAXTRIALS; trials++) {
 
@@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
                        valid = sp8870_read_data_valid_signal(state);
                        if (valid) {
                                dprintk("%s: delay = %i usec\n",
-                                       __FUNCTION__, check_count * 10);
+                                       __func__, check_count * 10);
                                break;
                        }
                        udelay(10);
@@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
        }
 
        if (!valid) {
-               printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
+               printk("%s: firmware crash!!!!!!\n", __func__);
                return -EIO;
        }
 
        if (debug) {
                if (valid) {
                        if (trials > 1) {
-                               printk("%s: firmware lockup!!!\n", __FUNCTION__);
-                               printk("%s: recovered after %i trial(s))\n",  __FUNCTION__, trials - 1);
+                               printk("%s: firmware lockup!!!\n", __func__);
+                               printk("%s: recovered after %i trial(s))\n",  __func__, trials - 1);
                                lockups++;
                        }
                }
                switches++;
-               printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
+               printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
        }
 
        return 0;
index 909cefe7139e2b623633caaa8e97cd51579eb602..a764a793c7d8204250e7ab80ec693ee9143e9a0e 100644 (file)
@@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
 static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_SP8870
index 1aa2539f5099b7528afb1cde568d48c97c0d1d9f..49f55877f51366f66e1b5225caf1e4fc756ad595 100644 (file)
@@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                printk ("%s: i2c write error (addr %02x, err == %i)\n",
-                       __FUNCTION__, state->config->demod_address, err);
+                       __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
 
@@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
                {
                        printk("%s: writereg error "
                               "(reg %03x, data %03x, ret == %i)\n",
-                              __FUNCTION__, reg & 0xffff, data & 0xffff, ret);
+                              __func__, reg & 0xffff, data & 0xffff, ret);
                        return ret;
                }
        }
@@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
                         { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
 
        if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-               printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               printk("%s: readreg error (ret == %i)\n", __func__, ret);
                return -1;
        }
 
@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
 
 static void sp887x_microcontroller_stop (struct sp887x_state* state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0xf08, 0x000);
        sp887x_writereg(state, 0xf09, 0x000);
 
@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
 
 static void sp887x_microcontroller_start (struct sp887x_state* state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0xf08, 0x000);
        sp887x_writereg(state, 0xf09, 0x000);
 
@@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state)
 static void sp887x_setup_agc (struct sp887x_state* state)
 {
        /* setup AGC parameters */
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        sp887x_writereg(state, 0x33c, 0x054);
        sp887x_writereg(state, 0x33b, 0x04c);
        sp887x_writereg(state, 0x328, 0x000);
@@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
        int fw_size = fw->size;
        unsigned char *mem = fw->data;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        /* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
        if (fw_size < FW_SIZE+10)
@@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
 
        sp887x_microcontroller_stop (state);
 
-       printk ("%s: firmware upload... ", __FUNCTION__);
+       printk ("%s: firmware upload... ", __func__);
 
        /* setup write pointer to -1 (end of memory) */
        /* bit 0x8000 in address is set to enable 13bit mode */
@@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
 
                if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
                        printk ("failed.\n");
-                       printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+                       printk ("%s: i2c error (err == %i)\n", __func__, err);
                        return err;
                }
        }
index 7ee78d7d916d1f8925c32ab5c36204825569bb40..04eff6e0eef3e6eb3b189a872d295aa356b70448 100644 (file)
@@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
 static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
                                          struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_SP887X
index 7c23775f77dbe0582734c49ee9ffe5e9f1904cbc..62caf802ed990b0343e50f8374c97f451b7a5e50 100644 (file)
@@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-                       "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
        // this device needs a STOP between the register and data
        if (state->config->stop_during_read) {
                if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
                if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
        } else {
                if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
                        return -1;
                }
        }
@@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
        // this device needs a STOP between the register and data
        if (state->config->stop_during_read) {
                if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
                if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
        } else {
                if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
                        return -1;
                }
        }
index 69f4515df2b9a0d84dd370f484347e684a72e652..3f8f9468f3878ffcd450a3976f7aea9d159da9dc 100644 (file)
@@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
 static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_STV0297
index 035dd7ba65194577aec5a8b52f30bfccfe14779c..17556183e871629c2ae4fabc116c598ce233ea70 100644 (file)
@@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-                       "ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
 
        if (ret != 2)
                dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-                               __FUNCTION__, reg, ret);
+                               __func__, reg, ret);
 
        return b1[0];
 }
@@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
        ret = i2c_transfer (state->i2c, msg, 2);
 
        if (ret != 2)
-               dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+               dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
 
        return ret == 2 ? 0 : ret;
 }
 
 static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
 {
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        switch (fec) {
        case FEC_AUTO:
@@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
                                             FEC_7_8, FEC_1_2 };
        u8 index;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        index = stv0299_readreg (state, 0x1b);
        index &= 0x7;
@@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
 {
        unsigned long start = jiffies;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        while (stv0299_readreg(state, 0x0a) & 1) {
                if (jiffies - start > timeout) {
-                       dprintk ("%s: timeout!!\n", __FUNCTION__);
+                       dprintk ("%s: timeout!!\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(10);
@@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
 {
        unsigned long start = jiffies;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
                if (jiffies - start > timeout) {
-                       dprintk ("%s: timeout!!\n", __FUNCTION__);
+                       dprintk ("%s: timeout!!\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(10);
@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
        u8 sfr[3];
        s8 rtf;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        stv0299_readregs (state, 0x1f, sfr, 3);
        stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
@@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
        offset = (s32) rtf * (srate / 4096L);
        offset /= 128;
 
-       dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
-       dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
+       dprintk ("%s : srate = %i\n", __func__, srate);
+       dprintk ("%s : ofset = %i\n", __func__, offset);
 
        srate += offset;
 
@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
        u8 val;
        int i;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (stv0299_wait_diseqc_idle (state, 100) < 0)
                return -ETIMEDOUT;
@@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
        struct stv0299_state* state = fe->demodulator_priv;
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (stv0299_wait_diseqc_idle (state, 100) < 0)
                return -ETIMEDOUT;
@@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
        u8 reg0x08;
        u8 reg0x0c;
 
-       dprintk("%s: %s\n", __FUNCTION__,
+       dprintk("%s: %s\n", __func__,
                voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
                voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
 
@@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
         *  H/V switching over OP0, OP1 and OP2 are LNB power enable bits
         */
        reg0x0c &= 0x0f;
-
-       if (voltage == SEC_VOLTAGE_OFF) {
-               stv0299_writeregI (state, 0x0c, 0x00); /*       LNB power off! */
-               return stv0299_writeregI (state, 0x08, 0x00); /*        LNB power off! */
-       }
-
-       stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
+       reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
-               if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10;
-               else reg0x0c |= 0x40;
-
-               return stv0299_writeregI(state, 0x0c, reg0x0c);
-
+               if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+                       reg0x0c |= 0x10; /* OP1 off, OP0 on */
+               else
+                       reg0x0c |= 0x40; /* OP1 on, OP0 off */
+               break;
        case SEC_VOLTAGE_18:
-               return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50);
+               reg0x0c |= 0x50; /* OP1 on, OP0 on */
+               break;
+       case SEC_VOLTAGE_OFF:
+               /* LNB power off! */
+               reg0x08 = 0x00;
+               reg0x0c = 0x00;
+               break;
        default:
                return -EINVAL;
        };
+
+       if (state->config->op0_off)
+               reg0x0c &= ~0x10;
+
+       stv0299_writeregI(state, 0x08, reg0x08);
+       return stv0299_writeregI(state, 0x0c, reg0x0c);
 }
 
 static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
 
        cmd = cmd << 1;
        if (debug_legacy_dish_switch)
-               printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
+               printk ("%s switch command: 0x%04lx\n",__func__, cmd);
 
        do_gettimeofday (&nexttime);
        if (debug_legacy_dish_switch)
@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
        }
        if (debug_legacy_dish_switch) {
                printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
-                       __FUNCTION__, fe->dvb->num);
+                       __func__, fe->dvb->num);
                for (i = 1; i < 10; i++)
                        printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
        }
@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
 {
        struct stv0299_state* state = fe->demodulator_priv;
        int i;
+       u8 reg;
+       u8 val;
 
        dprintk("stv0299: init chip\n");
 
-       for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
-               stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
+       for (i = 0; ; i += 2)  {
+               reg = state->config->inittab[i];
+               val = state->config->inittab[i+1];
+               if (reg == 0xff && val == 0xff)
+                       break;
+               if (reg == 0x0c && state->config->op0_off)
+                       val &= ~0x10;
+               stv0299_writeregI(state, reg, val);
+       }
 
        return 0;
 }
@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
        u8 signal = 0xff - stv0299_readreg (state, 0x18);
        u8 sync = stv0299_readreg (state, 0x1b);
 
-       dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
+       dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
        *status = 0;
 
        if (signal > 10)
@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
        s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
                               | stv0299_readreg (state, 0x19));
 
-       dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
+       dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
                 stv0299_readreg (state, 0x18),
                 stv0299_readreg (state, 0x19), (int) signal);
 
@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        struct stv0299_state* state = fe->demodulator_priv;
        int invval = 0;
 
-       dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
+       dprintk ("%s : FE_SET_FRONTEND\n", __func__);
 
        // set the inversion
        if (p->inversion == INVERSION_OFF) invval = 0;
index 33df9495908fb8a1a4f9d9afb67bd53b3756a6b8..3282f43022f5da37d2681e34a20c235e94828176 100644 (file)
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#define STV0229_LOCKOUTPUT_0  0
-#define STV0229_LOCKOUTPUT_1  1
-#define STV0229_LOCKOUTPUT_CF 2
-#define STV0229_LOCKOUTPUT_LK 3
+#define STV0299_LOCKOUTPUT_0  0
+#define STV0299_LOCKOUTPUT_1  1
+#define STV0299_LOCKOUTPUT_CF 2
+#define STV0299_LOCKOUTPUT_LK 3
 
 #define STV0299_VOLT13_OP0 0
 #define STV0299_VOLT13_OP1 1
@@ -82,6 +82,9 @@ struct stv0299_config
        /* Is 13v controlled by OP0 or OP1? */
        u8 volt13_op0_op1:1;
 
+       /* Turn-off OP0? */
+       u8 op0_off:1;
+
        /* minimum delay before retuning */
        int min_delay_ms;
 
@@ -96,7 +99,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
 static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_STV0299
index 45137d2ebfb9846b3462e20981eb0dd91adc0973..f648fdb64bb7dd33753522bb70e6619bc8c42f87 100644 (file)
@@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
        if (ret != 1)
                printk("DVB: TDA10021(%d): %s, writereg error "
                        "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+                       state->frontend.dvb->num, __func__, reg, data, ret);
 
        msleep(10);
        return (ret != 1) ? -EREMOTEIO : 0;
@@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
        // Don't print an error message if the id is read.
        if (ret != 2 && reg != 0x1a)
                printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
-                               __FUNCTION__, ret);
+                               __func__, ret);
        return b1[0];
 }
 
index 364bc01971a0c7c4071ac98d0fd9f6e5e86fced8..0727b80bc4d296a83f56317b9266fdbac705f562 100644 (file)
@@ -118,7 +118,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
        ret = i2c_transfer (state->i2c, msg, 2);
        if (ret != 2)
                printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
-                                __FUNCTION__, ret);
+                                __func__, ret);
        return b1[0];
 }
 
@@ -132,7 +132,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
        if (ret != 1)
                printk("DVB: TDA10023(%d): %s, writereg error "
                        "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+                       state->frontend.dvb->num, __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
index e9094d8123f6bb5ffb02473eff90fa12efd42999..1bcc0d44b90bf789d33b73d5bb93b96014f6ec02 100644 (file)
@@ -40,7 +40,7 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config
 static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA10021
@@ -52,7 +52,7 @@ extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config
 static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA10023
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
new file mode 100644 (file)
index 0000000..090fb7d
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "tda10048.h"
+
+#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
+#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
+
+/* Register name definitions */
+#define TDA10048_IDENTITY          0x00
+#define TDA10048_VERSION           0x01
+#define TDA10048_DSP_CODE_CPT      0x0C
+#define TDA10048_DSP_CODE_IN       0x0E
+#define TDA10048_IN_CONF1          0x10
+#define TDA10048_IN_CONF2          0x11
+#define TDA10048_IN_CONF3          0x12
+#define TDA10048_OUT_CONF1         0x14
+#define TDA10048_OUT_CONF2         0x15
+#define TDA10048_OUT_CONF3         0x16
+#define TDA10048_AUTO              0x18
+#define TDA10048_SYNC_STATUS       0x1A
+#define TDA10048_CONF_C4_1         0x1E
+#define TDA10048_CONF_C4_2         0x1F
+#define TDA10048_CODE_IN_RAM       0x20
+#define TDA10048_CHANNEL_INFO_1_R  0x22
+#define TDA10048_CHANNEL_INFO_2_R  0x23
+#define TDA10048_CHANNEL_INFO1     0x24
+#define TDA10048_CHANNEL_INFO2     0x25
+#define TDA10048_TIME_ERROR_R      0x26
+#define TDA10048_TIME_ERROR        0x27
+#define TDA10048_FREQ_ERROR_LSB_R  0x28
+#define TDA10048_FREQ_ERROR_MSB_R  0x29
+#define TDA10048_FREQ_ERROR_LSB    0x2A
+#define TDA10048_FREQ_ERROR_MSB    0x2B
+#define TDA10048_IT_SEL            0x30
+#define TDA10048_IT_STAT           0x32
+#define TDA10048_DSP_AD_LSB        0x3C
+#define TDA10048_DSP_AD_MSB        0x3D
+#define TDA10048_DSP_REF_LSB       0x3E
+#define TDA10048_DSP_REF_MSB       0x3F
+#define TDA10048_CONF_TRISTATE1    0x44
+#define TDA10048_CONF_TRISTATE2    0x45
+#define TDA10048_CONF_POLARITY     0x46
+#define TDA10048_GPIO_SP_DS0       0x48
+#define TDA10048_GPIO_SP_DS1       0x49
+#define TDA10048_GPIO_SP_DS2       0x4A
+#define TDA10048_GPIO_SP_DS3       0x4B
+#define TDA10048_GPIO_OUT_SEL      0x4C
+#define TDA10048_GPIO_SELECT       0x4D
+#define TDA10048_IC_MODE           0x4E
+#define TDA10048_CONF_XO           0x50
+#define TDA10048_CONF_PLL1         0x51
+#define TDA10048_CONF_PLL2         0x52
+#define TDA10048_CONF_PLL3         0x53
+#define TDA10048_CONF_ADC          0x54
+#define TDA10048_CONF_ADC_2        0x55
+#define TDA10048_CONF_C1_1         0x60
+#define TDA10048_CONF_C1_3         0x62
+#define TDA10048_AGC_CONF          0x70
+#define TDA10048_AGC_THRESHOLD_LSB 0x72
+#define TDA10048_AGC_THRESHOLD_MSB 0x73
+#define TDA10048_AGC_RENORM        0x74
+#define TDA10048_AGC_GAINS         0x76
+#define TDA10048_AGC_TUN_MIN       0x78
+#define TDA10048_AGC_TUN_MAX       0x79
+#define TDA10048_AGC_IF_MIN        0x7A
+#define TDA10048_AGC_IF_MAX        0x7B
+#define TDA10048_AGC_TUN_LEVEL     0x7E
+#define TDA10048_AGC_IF_LEVEL      0x7F
+#define TDA10048_DIG_AGC_LEVEL     0x81
+#define TDA10048_FREQ_PHY2_LSB     0x86
+#define TDA10048_FREQ_PHY2_MSB     0x87
+#define TDA10048_TIME_INVWREF_LSB  0x88
+#define TDA10048_TIME_INVWREF_MSB  0x89
+#define TDA10048_TIME_WREF_LSB     0x8A
+#define TDA10048_TIME_WREF_MID1    0x8B
+#define TDA10048_TIME_WREF_MID2    0x8C
+#define TDA10048_TIME_WREF_MSB     0x8D
+#define TDA10048_NP_OUT            0xA2
+#define TDA10048_CELL_ID_LSB       0xA4
+#define TDA10048_CELL_ID_MSB       0xA5
+#define TDA10048_EXTTPS_ODD        0xAA
+#define TDA10048_EXTTPS_EVEN       0xAB
+#define TDA10048_TPS_LENGTH        0xAC
+#define TDA10048_FREE_REG_1        0xB2
+#define TDA10048_FREE_REG_2        0xB3
+#define TDA10048_CONF_C3_1         0xC0
+#define TDA10048_CYBER_CTRL        0xC2
+#define TDA10048_CBER_NMAX_LSB     0xC4
+#define TDA10048_CBER_NMAX_MSB     0xC5
+#define TDA10048_CBER_LSB          0xC6
+#define TDA10048_CBER_MSB          0xC7
+#define TDA10048_VBER_LSB          0xC8
+#define TDA10048_VBER_MID          0xC9
+#define TDA10048_VBER_MSB          0xCA
+#define TDA10048_CYBER_LUT         0xCC
+#define TDA10048_UNCOR_CTRL        0xCD
+#define TDA10048_UNCOR_CPT_LSB     0xCE
+#define TDA10048_UNCOR_CPT_MSB     0xCF
+#define TDA10048_SOFT_IT_C3        0xD6
+#define TDA10048_CONF_TS2          0xE0
+#define TDA10048_CONF_TS1          0xE1
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug >= level)\
+               printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
+       } while (0)
+
+struct tda10048_state {
+
+       struct i2c_adapter *i2c;
+
+       /* configuration settings */
+       const struct tda10048_config *config;
+       struct dvb_frontend frontend;
+
+       int fwloaded;
+};
+
+static struct init_tab {
+       u8      reg;
+       u16     data;
+} init_tab[] = {
+       { TDA10048_CONF_PLL1, 0x08 },
+       { TDA10048_CONF_ADC_2, 0x00 },
+       { TDA10048_CONF_C4_1, 0x00 },
+       { TDA10048_CONF_PLL1, 0x0f },
+       { TDA10048_CONF_PLL2, 0x0a },
+       { TDA10048_CONF_PLL3, 0x43 },
+       { TDA10048_FREQ_PHY2_LSB, 0x02 },
+       { TDA10048_FREQ_PHY2_MSB, 0x0a },
+       { TDA10048_TIME_WREF_LSB, 0xbd },
+       { TDA10048_TIME_WREF_MID1, 0xe4 },
+       { TDA10048_TIME_WREF_MID2, 0xa8 },
+       { TDA10048_TIME_WREF_MSB, 0x02 },
+       { TDA10048_TIME_INVWREF_LSB, 0x04 },
+       { TDA10048_TIME_INVWREF_MSB, 0x06 },
+       { TDA10048_CONF_C4_1, 0x00 },
+       { TDA10048_CONF_C1_1, 0xa8 },
+       { TDA10048_AGC_CONF, 0x16 },
+       { TDA10048_CONF_C1_3, 0x0b },
+       { TDA10048_AGC_TUN_MIN, 0x00 },
+       { TDA10048_AGC_TUN_MAX, 0xff },
+       { TDA10048_AGC_IF_MIN, 0x00 },
+       { TDA10048_AGC_IF_MAX, 0xff },
+       { TDA10048_AGC_THRESHOLD_MSB, 0x00 },
+       { TDA10048_AGC_THRESHOLD_LSB, 0x70 },
+       { TDA10048_CYBER_CTRL, 0x38 },
+       { TDA10048_AGC_GAINS, 0x12 },
+       { TDA10048_CONF_XO, 0x00 },
+       { TDA10048_CONF_TS1, 0x07 },
+       { TDA10048_IC_MODE, 0x00 },
+       { TDA10048_CONF_TS2, 0xc0 },
+       { TDA10048_CONF_TRISTATE1, 0x21 },
+       { TDA10048_CONF_TRISTATE2, 0x00 },
+       { TDA10048_CONF_POLARITY, 0x00 },
+       { TDA10048_CONF_C4_2, 0x04 },
+       { TDA10048_CONF_ADC, 0x60 },
+       { TDA10048_CONF_ADC_2, 0x10 },
+       { TDA10048_CONF_ADC, 0x60 },
+       { TDA10048_CONF_ADC_2, 0x00 },
+       { TDA10048_CONF_C1_1, 0xa8 },
+       { TDA10048_UNCOR_CTRL, 0x00 },
+       { TDA10048_CONF_C4_2, 0x04 },
+};
+
+static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 buf [] = { reg, data };
+       struct i2c_msg msg = {
+               .addr = state->config->demod_address,
+               .flags = 0, .buf = buf, .len = 2 };
+
+       dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk("%s: writereg error (ret == %i)\n", __func__, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+
+static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
+{
+       int ret;
+       u8 b0 [] = { reg };
+       u8 b1 [] = { 0 };
+       struct i2c_msg msg [] = {
+               { .addr = state->config->demod_address,
+                       .flags = 0, .buf = b0, .len = 1 },
+               { .addr = state->config->demod_address,
+                       .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+       dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                       __func__, ret);
+
+       return b1[0];
+}
+
+static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
+       u8 *data, u16 len)
+{
+       int ret = -EREMOTEIO;
+       struct i2c_msg msg;
+       u8 *buf;
+
+       dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
+
+       buf = kmalloc(len + 1, GFP_KERNEL);
+       if (buf == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       *buf = reg;
+       memcpy(buf + 1, data, len);
+
+       msg.addr = state->config->demod_address;
+       msg.flags = 0;
+       msg.buf = buf;
+       msg.len = len + 1;
+
+       dprintk(2, "%s():  write len = %d\n",
+               __func__, msg.len);
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+       if (ret != 1) {
+               printk(KERN_ERR "%s(): writereg error err %i\n",
+                        __func__, ret);
+               ret = -EREMOTEIO;
+       }
+
+error:
+       kfree(buf);
+
+       return ret;
+}
+
+static int tda10048_firmware_upload(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       const struct firmware *fw;
+       int ret;
+       int pos = 0;
+       int cnt;
+       u8 wlen = state->config->fwbulkwritelen;
+
+       if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
+               wlen = TDA10048_BULKWRITE_200;
+
+       /* request the firmware, this will block and timeout */
+       printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
+               __func__,
+               TDA10048_DEFAULT_FIRMWARE);
+
+       ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
+               &state->i2c->dev);
+       if (ret) {
+               printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
+                       __func__);
+               return -EIO;
+       } else {
+               printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
+                       __func__,
+                       fw->size);
+               ret = 0;
+       }
+
+       if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
+               printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
+               return -EIO;
+       } else {
+               printk(KERN_INFO "%s: firmware uploading\n", __func__);
+
+               /* Soft reset */
+               tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+                       tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+                               & 0xfe);
+               tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+                       tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+                               | 0x01);
+
+               /* Put the demod into host download mode */
+               tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
+
+               /* Boot the DSP */
+               tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
+
+               /* Prepare for download */
+               tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
+
+               /* Download the firmware payload */
+               while (pos < fw->size) {
+
+                       if ((fw->size - pos) > wlen)
+                               cnt = wlen;
+                       else
+                               cnt = fw->size - pos;
+
+                       tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
+                               &fw->data[pos], cnt);
+
+                       pos += cnt;
+               }
+
+               ret = -EIO;
+               /* Wait up to 250ms for the DSP to boot */
+               for (cnt = 0; cnt < 250 ; cnt += 10) {
+
+                       msleep(10);
+
+                       if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
+                               & 0x40) {
+                               ret = 0;
+                               break;
+                       }
+               }
+       }
+
+       release_firmware(fw);
+
+       if (ret == 0) {
+               printk(KERN_INFO "%s: firmware uploaded\n", __func__);
+               state->fwloaded = 1;
+       } else
+               printk(KERN_ERR "%s: firmware upload failed\n", __func__);
+
+       return ret;
+}
+
+static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s(%d)\n", __func__, inversion);
+
+       if (inversion == TDA10048_INVERSION_ON)
+               tda10048_writereg(state, TDA10048_CONF_C1_1,
+                       tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
+       else
+               tda10048_writereg(state, TDA10048_CONF_C1_1,
+                       tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
+
+       return 0;
+}
+
+/* Retrieve the demod settings */
+static int tda10048_get_tps(struct tda10048_state *state,
+       struct dvb_ofdm_parameters *p)
+{
+       u8 val;
+
+       /* Make sure the TPS regs are valid */
+       if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
+               return -EAGAIN;
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF2);
+       switch ((val & 0x60) >> 5) {
+       case 0: p->constellation =   QPSK; break;
+       case 1: p->constellation = QAM_16; break;
+       case 2: p->constellation = QAM_64; break;
+       }
+       switch ((val & 0x18) >> 3) {
+       case 0: p->hierarchy_information = HIERARCHY_NONE; break;
+       case 1: p->hierarchy_information =    HIERARCHY_1; break;
+       case 2: p->hierarchy_information =    HIERARCHY_2; break;
+       case 3: p->hierarchy_information =    HIERARCHY_4; break;
+       }
+       switch (val & 0x07) {
+       case 0: p->code_rate_HP = FEC_1_2; break;
+       case 1: p->code_rate_HP = FEC_2_3; break;
+       case 2: p->code_rate_HP = FEC_3_4; break;
+       case 3: p->code_rate_HP = FEC_5_6; break;
+       case 4: p->code_rate_HP = FEC_7_8; break;
+       }
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF3);
+       switch (val & 0x07) {
+       case 0: p->code_rate_LP = FEC_1_2; break;
+       case 1: p->code_rate_LP = FEC_2_3; break;
+       case 2: p->code_rate_LP = FEC_3_4; break;
+       case 3: p->code_rate_LP = FEC_5_6; break;
+       case 4: p->code_rate_LP = FEC_7_8; break;
+       }
+
+       val = tda10048_readreg(state, TDA10048_OUT_CONF1);
+       switch ((val & 0x0c) >> 2) {
+       case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
+       case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
+       case 2: p->guard_interval =  GUARD_INTERVAL_1_8; break;
+       case 3: p->guard_interval =  GUARD_INTERVAL_1_4; break;
+       }
+       switch (val & 0x02) {
+       case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
+       case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+       }
+
+       return 0;
+}
+
+static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
+       else
+               return tda10048_writereg(state, TDA10048_CONF_C4_1,
+                       tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
+}
+
+static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s(%d)\n", __func__, serial);
+
+       /* Ensure pins are out of tri-state */
+       tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
+       tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
+
+       if (serial) {
+               tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
+               tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
+       } else {
+               tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
+               tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
+       }
+
+       return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+/* TODO: Support manual tuning with specific params */
+static int tda10048_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+
+       if (fe->ops.tuner_ops.set_params) {
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               fe->ops.tuner_ops.set_params(fe, p);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       /* Enable demod TPS auto detection and begin acquisition */
+       tda10048_writereg(state, TDA10048_AUTO, 0x57);
+
+       return 0;
+}
+
+/* Establish sane defaults and load firmware. */
+static int tda10048_init(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       int ret = 0, i;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Apply register defaults */
+       for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+               tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+       if (state->fwloaded == 0)
+               ret = tda10048_firmware_upload(fe);
+
+       /* Set either serial or parallel */
+       tda10048_output_mode(fe, state->config->output_mode);
+
+       /* set inversion */
+       tda10048_set_inversion(fe, state->config->inversion);
+
+       /* Ensure we leave the gate closed */
+       tda10048_i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 reg;
+
+       *status = 0;
+
+       reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
+
+       dprintk(1, "%s() status =0x%02x\n", __func__, reg);
+
+       if (reg & 0x02)
+               *status |= FE_HAS_CARRIER;
+
+       if (reg & 0x04)
+               *status |= FE_HAS_SIGNAL;
+
+       if (reg & 0x08) {
+               *status |= FE_HAS_LOCK;
+               *status |= FE_HAS_VITERBI;
+               *status |= FE_HAS_SYNC;
+       }
+
+       return 0;
+}
+
+static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* TODO: A reset may be required here */
+       *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
+               tda10048_readreg(state, TDA10048_CBER_LSB);
+
+       return 0;
+}
+
+static int tda10048_read_signal_strength(struct dvb_frontend *fe,
+       u16 *signal_strength)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 v;
+
+       dprintk(1, "%s()\n", __func__);
+
+       *signal_strength = 65535;
+
+       v = tda10048_readreg(state, TDA10048_NP_OUT);
+       if (v > 0)
+               *signal_strength -= (v << 8) | v;
+
+       return 0;
+}
+
+/* SNR lookup table */
+static struct snr_tab {
+       u8 val;
+       u8 data;
+} snr_tab[] = {
+       {   0,   0 },
+       {   1, 246 },
+       {   2, 215 },
+       {   3, 198 },
+       {   4, 185 },
+       {   5, 176 },
+       {   6, 168 },
+       {   7, 161 },
+       {   8, 155 },
+       {   9, 150 },
+       {  10, 146 },
+       {  11, 141 },
+       {  12, 138 },
+       {  13, 134 },
+       {  14, 131 },
+       {  15, 128 },
+       {  16, 125 },
+       {  17, 122 },
+       {  18, 120 },
+       {  19, 118 },
+       {  20, 115 },
+       {  21, 113 },
+       {  22, 111 },
+       {  23, 109 },
+       {  24, 107 },
+       {  25, 106 },
+       {  26, 104 },
+       {  27, 102 },
+       {  28, 101 },
+       {  29,  99 },
+       {  30,  98 },
+       {  31,  96 },
+       {  32,  95 },
+       {  33,  94 },
+       {  34,  92 },
+       {  35,  91 },
+       {  36,  90 },
+       {  37,  89 },
+       {  38,  88 },
+       {  39,  86 },
+       {  40,  85 },
+       {  41,  84 },
+       {  42,  83 },
+       {  43,  82 },
+       {  44,  81 },
+       {  45,  80 },
+       {  46,  79 },
+       {  47,  78 },
+       {  48,  77 },
+       {  49,  76 },
+       {  50,  76 },
+       {  51,  75 },
+       {  52,  74 },
+       {  53,  73 },
+       {  54,  72 },
+       {  56,  71 },
+       {  57,  70 },
+       {  58,  69 },
+       {  60,  68 },
+       {  61,  67 },
+       {  63,  66 },
+       {  64,  65 },
+       {  66,  64 },
+       {  67,  63 },
+       {  68,  62 },
+       {  69,  62 },
+       {  70,  61 },
+       {  72,  60 },
+       {  74,  59 },
+       {  75,  58 },
+       {  77,  57 },
+       {  79,  56 },
+       {  81,  55 },
+       {  83,  54 },
+       {  85,  53 },
+       {  87,  52 },
+       {  89,  51 },
+       {  91,  50 },
+       {  93,  49 },
+       {  95,  48 },
+       {  97,  47 },
+       { 100,  46 },
+       { 102,  45 },
+       { 104,  44 },
+       { 107,  43 },
+       { 109,  42 },
+       { 112,  41 },
+       { 114,  40 },
+       { 117,  39 },
+       { 120,  38 },
+       { 123,  37 },
+       { 125,  36 },
+       { 128,  35 },
+       { 131,  34 },
+       { 134,  33 },
+       { 138,  32 },
+       { 141,  31 },
+       { 144,  30 },
+       { 147,  29 },
+       { 151,  28 },
+       { 154,  27 },
+       { 158,  26 },
+       { 162,  25 },
+       { 165,  24 },
+       { 169,  23 },
+       { 173,  22 },
+       { 177,  21 },
+       { 181,  20 },
+       { 186,  19 },
+       { 190,  18 },
+       { 194,  17 },
+       { 199,  16 },
+       { 204,  15 },
+       { 208,  14 },
+       { 213,  13 },
+       { 218,  12 },
+       { 223,  11 },
+       { 229,  10 },
+       { 234,   9 },
+       { 239,   8 },
+       { 245,   7 },
+       { 251,   6 },
+       { 255,   5 },
+};
+
+static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       u8 v;
+       int i, ret = -EINVAL;
+
+       dprintk(1, "%s()\n", __func__);
+
+       v = tda10048_readreg(state, TDA10048_NP_OUT);
+       for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
+               if (v <= snr_tab[i].val) {
+                       *snr = snr_tab[i].data;
+                       ret = 0;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
+               tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
+
+       return 0;
+}
+
+static int tda10048_get_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
+               & 0x20 ? INVERSION_ON : INVERSION_OFF;
+
+       return tda10048_get_tps(state, &p->u.ofdm);
+}
+
+static int tda10048_get_tune_settings(struct dvb_frontend *fe,
+       struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void tda10048_release(struct dvb_frontend *fe)
+{
+       struct tda10048_state *state = fe->demodulator_priv;
+       dprintk(1, "%s()\n", __func__);
+       kfree(state);
+}
+
+static struct dvb_frontend_ops tda10048_ops;
+
+struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
+       struct i2c_adapter *i2c)
+{
+       struct tda10048_state *state = NULL;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->fwloaded = 0;
+
+       /* check if the demod is present */
+       if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &tda10048_ops,
+               sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       /* Leave the gate closed */
+       tda10048_i2c_gate_ctrl(&state->frontend, 0);
+
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(tda10048_attach);
+
+static struct dvb_frontend_ops tda10048_ops = {
+
+       .info = {
+               .name                   = "NXP TDA10048HN DVB-T",
+               .type                   = FE_OFDM,
+               .frequency_min          = 177000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 166666,
+               .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+               FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+               FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+       },
+
+       .release = tda10048_release,
+       .init = tda10048_init,
+       .i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
+       .set_frontend = tda10048_set_frontend,
+       .get_frontend = tda10048_get_frontend,
+       .get_tune_settings = tda10048_get_tune_settings,
+       .read_status = tda10048_read_status,
+       .read_ber = tda10048_read_ber,
+       .read_signal_strength = tda10048_read_signal_strength,
+       .read_snr = tda10048_read_snr,
+       .read_ucblocks = tda10048_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
new file mode 100644 (file)
index 0000000..2b5c78e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef TDA10048_H
+#define TDA10048_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct tda10048_config {
+
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* serial/parallel output */
+#define TDA10048_PARALLEL_OUTPUT 0
+#define TDA10048_SERIAL_OUTPUT   1
+       u8 output_mode;
+
+#define TDA10048_BULKWRITE_200 200
+#define TDA10048_BULKWRITE_50  50
+       u8 fwbulkwritelen;
+
+       /* Spectral Inversion */
+#define TDA10048_INVERSION_OFF 0
+#define TDA10048_INVERSION_ON  1
+       u8 inversion;
+};
+
+#if defined(CONFIG_DVB_TDA10048) || \
+       (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10048_attach(
+       const struct tda10048_config *config,
+       struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10048_attach(
+       const struct tda10048_config *config,
+       struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_TDA10048 */
+
+#endif /* TDA10048_H */
index 8415a8a5247a09381f196ead24b4935d5b680c73..49973846373e843b5fc4d64e6aa97b14922f3a45 100644 (file)
@@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
        u8 buf[] = { reg, data };
        struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
+       dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
 
        msg.addr = state->config->demod_address;
        ret = i2c_transfer(state->i2c, &msg, 1);
 
        if (ret != 1)
                dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
-       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
                reg, data, ret);
        return (ret != 1) ? -1 : 0;
 }
@@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
        struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
                                { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
 
-       dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
+       dprintk("%s: reg=0x%x\n", __func__, reg);
 
        msg[0].addr = state->config->demod_address;
        msg[1].addr = state->config->demod_address;
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+               dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
                        ret);
                return -1;
        }
 
-       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+       dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
                reg, b1[0], ret);
        return b1[0];
 }
@@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
 static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
 {
        int val;
-       dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
+       dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
                mask, data);
 
        // read a byte and check
@@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
        int i;
        int result;
 
-       dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
+       dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
 
        result = 0;
        for (i = 0; i < len; i++) {
@@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
 static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
 {
        int result;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
        msleep(20);
@@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
 
 static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
 }
@@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
                }
                pos += tx_size;
 
-               dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
+               dprintk("%s: fw_pos=0x%x\n", __func__, pos);
        }
        // give the DSP a chance to settle 03/10/05 Hac
        msleep(100);
@@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
                tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
        }
        if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
-               dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
+               dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
                tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
        } else {
-               dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
+               dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
                tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
        }
        if(tda10046_clk53m)
@@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
        if (state->config->xtal_freq == TDA10046_XTAL_4M) {
                tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
        } else {
-               dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__);
+               dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
                tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
        }
        tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
@@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (tda10045_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe)
 static int tda10046_init(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (tda10046_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        int tmp;
        int inversion;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
                // setup auto offset
@@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // inversion status
        fe_params->inversion = INVERSION_OFF;
@@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
        int cber;
        int vber;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read status
        status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
@@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
        }
 
        // success
-       dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
+       dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
        return 0;
 }
 
@@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
        int tmp;
        int reg = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // determine the register to use
        switch (state->demod_type) {
@@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
                return -EIO;
 
        *signal = (tmp << 8) | tmp;
-       dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
+       dprintk("%s: signal=0x%x\n", __func__, *signal);
        return 0;
 }
 
@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
        struct tda1004x_state* state = fe->demodulator_priv;
        int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read it
        tmp = tda1004x_read_byte(state, TDA1004X_SNR);
@@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
        tmp = 255 - tmp;
 
        *snr = ((tmp << 8) | tmp);
-       dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
+       dprintk("%s: snr=0x%x\n", __func__, *snr);
        return 0;
 }
 
@@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        int tmp2;
        int counter;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read the UCBLOCKS and reset
        counter = 0;
@@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        else
                *ucblocks = 0xffffffff;
 
-       dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
+       dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
        return 0;
 }
 
@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
        struct tda1004x_state* state = fe->demodulator_priv;
        int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        // read it in
        tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
@@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
        // The address 0x20 should be read to cope with a TDA10046 bug
        tda1004x_read_byte(state, TDA1004X_CBER_RESET);
 
-       dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
+       dprintk("%s: ber=0x%x\n", __func__, *ber);
        return 0;
 }
 
index abae84350142a023bfec7be21f257995b3d1ebfe..4e27ffb0f14e80d189056e66b8e6822e593d31a3 100644 (file)
@@ -94,7 +94,6 @@ struct tda1004x_config
 
        /* slave address and configuration of the tuner */
        u8 tuner_address;
-       u8 tuner_config;
        u8 antenna_switch;
 
        /* if the board uses another I2c Bridge (tda8290), its address */
@@ -128,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config
 static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA1004X
index 0d2b69a99ad454385a2520a0debd7d5e11e0f9d5..a17ce3c4ad860c8959609e22c56679e5a004fda1 100644 (file)
@@ -43,7 +43,7 @@ struct tda10086_state {
        bool has_lock;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk(args...) \
        do { \
                if (debug) printk(KERN_DEBUG "tda10086: " args); \
@@ -60,7 +60,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
 
        if (ret != 1)
                dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-                       __FUNCTION__, reg, data, ret);
+                       __func__, reg, data, ret);
 
        return (ret != 1) ? ret : 0;
 }
@@ -78,7 +78,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg)
        ret = i2c_transfer(state->i2c, msg, 2);
 
        if (ret != 2) {
-               dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+               dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
                        ret);
                return ret;
        }
@@ -90,16 +90,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
 {
        int val;
 
-       // read a byte and check
+       /* read a byte and check */
        val = tda10086_read_byte(state, reg);
        if (val < 0)
                return val;
 
-       // mask if off
+       /* mask if off */
        val = val & ~mask;
        val |= data & 0xff;
 
-       // write it out again
+       /* write it out again */
        return tda10086_write_byte(state, reg, val);
 }
 
@@ -108,62 +108,67 @@ static int tda10086_init(struct dvb_frontend* fe)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
-       // reset
+       /* reset */
        tda10086_write_byte(state, 0x00, 0x00);
        msleep(10);
 
-       // misc setup
+       /* misc setup */
        tda10086_write_byte(state, 0x01, 0x94);
-       tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
+       tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
        tda10086_write_byte(state, 0x03, 0xe4);
        tda10086_write_byte(state, 0x04, 0x43);
        tda10086_write_byte(state, 0x0c, 0x0c);
-       tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
-       tda10086_write_byte(state, 0x20, 0x89); // misc
-       tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
-       tda10086_write_byte(state, 0x32, 0x00); // irq off
-       tda10086_write_byte(state, 0x31, 0x56); // setup AFC
-
-       // setup PLL (assumes 16Mhz XIN)
-       tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
-       tda10086_write_byte(state, 0x3a, 0x0b); // M=12
-       tda10086_write_byte(state, 0x3b, 0x01); // P=2
-       tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
-
-       // setup TS interface
+       tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
+       tda10086_write_byte(state, 0x20, 0x89); /* misc */
+       tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
+       tda10086_write_byte(state, 0x32, 0x00); /* irq off */
+       tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
+
+       /* setup PLL (this assumes SACLK = 96MHz) */
+       tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
+       if (state->config->xtal_freq == TDA10086_XTAL_16M) {
+               tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
+               tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
+       } else {
+               tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
+               tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
+       }
+       tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
+
+       /* setup TS interface */
        tda10086_write_byte(state, 0x11, 0x81);
        tda10086_write_byte(state, 0x12, 0x81);
-       tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
-       tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
-       tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
+       tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
+       tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
+       tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
        tda10086_write_byte(state, 0x10, 0x2a);
 
-       // setup ADC
-       tda10086_write_byte(state, 0x58, 0x61); // ADC setup
-       tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
+       /* setup ADC */
+       tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
+       tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
 
-       // setup AGC
+       /* setup AGC */
        tda10086_write_byte(state, 0x05, 0x0B);
        tda10086_write_byte(state, 0x37, 0x63);
-       tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
+       tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
        tda10086_write_byte(state, 0x40, 0x64);
        tda10086_write_byte(state, 0x41, 0x4f);
        tda10086_write_byte(state, 0x42, 0x43);
 
-       // setup viterbi
-       tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
+       /* setup viterbi */
+       tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
 
-       // setup carrier recovery
+       /* setup carrier recovery */
        tda10086_write_byte(state, 0x3d, 0x80);
 
-       // setup SEC
-       tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
-       tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));      // } tone frequency
-       tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
+       /* setup SEC */
+       tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
+       tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
+       tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
 
        return 0;
 }
@@ -173,7 +178,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
        unsigned long timeout = jiffies + msecs_to_jiffies(200);
        while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
                if(time_after(jiffies, timeout)) {
-                       printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+                       printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
                        break;
                }
                msleep(10);
@@ -185,7 +190,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -211,7 +216,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
        u8 oldval;
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -239,7 +244,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
        u8 oldval = tda10086_read_byte(state, 0x36);
        u8 t22k_off = 0x80;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (state->config->diseqc_tone)
                t22k_off = 0;
@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
 {
        u8 invval = 0x80;
 
-       dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
+       dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
 
        switch(fe_params->inversion) {
        case INVERSION_OFF:
@@ -300,9 +305,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
        u32 bdri;
        u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
 
-       dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
+       dprintk ("%s %i\n", __func__, symbol_rate);
 
-       // setup the decimation and anti-aliasing filters..
+       /* setup the decimation and anti-aliasing filters.. */
        if (symbol_rate < (u32) (SACLK * 0.0137)) {
                dfn=4;
                afs=1;
@@ -339,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
                byp=1;
        }
 
-       // calculate BDR
+       /* calculate BDR */
        big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
        big += ((SACLK/1000ULL)-1ULL);
        do_div(big, (SACLK/1000ULL));
        bdr = big & 0xfffff;
 
-       // calculate BDRI
+       /* calculate BDRI */
        tmp = (1<<dfn)*(symbol_rate/1000);
        bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
 
@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
 {
        u8 fecval;
 
-       dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
+       dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
 
        switch(fe_params->u.qpsk.fec_inner) {
        case FEC_1_2:
@@ -412,13 +417,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
        u32 freq = 0;
        int freqoff;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // modify parameters for tuning
+       /* modify parameters for tuning */
        tda10086_write_byte(state, 0x02, 0x35);
        state->has_lock = false;
 
-       // set params
+       /* set params */
        if (fe->ops.tuner_ops.set_params) {
                fe->ops.tuner_ops.set_params(fe, fe_params);
                if (fe->ops.i2c_gate_ctrl)
@@ -430,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
-       // calcluate the frequency offset (in *Hz* not kHz)
+       /* calcluate the frequency offset (in *Hz* not kHz) */
        freqoff = fe_params->frequency - freq;
        freqoff = ((1<<16) * freqoff) / (SACLK/1000);
        tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
@@ -443,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
        if ((ret = tda10086_set_fec(state, fe_params)) < 0)
                return ret;
 
-       // soft reset + disable TS output until lock
+       /* soft reset + disable TS output until lock */
        tda10086_write_mask(state, 0x10, 0x40, 0x40);
        tda10086_write_mask(state, 0x00, 0x01, 0x00);
 
@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        int tmp;
        u64 tmp64;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // check for invalid symbol rate
+       /* check for invalid symbol rate */
        if (fe_params->u.qpsk.symbol_rate < 500000)
                return -EINVAL;
 
-       // calculate the updated frequency (note: we convert from Hz->kHz)
+       /* calculate the updated frequency (note: we convert from Hz->kHz) */
        tmp64 = tda10086_read_byte(state, 0x52);
        tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
        if (tmp64 & 0x8000)
@@ -474,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        do_div(tmp64, (1ULL<<15) * (1ULL<<1));
        fe_params->frequency = (int) state->frequency + (int) tmp64;
 
-       // the inversion
+       /* the inversion */
        val = tda10086_read_byte(state, 0x0c);
        if (val & 0x80) {
                switch(val & 0x40) {
@@ -505,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
                }
        }
 
-       // calculate the updated symbol rate
+       /* calculate the updated symbol rate */
        tmp = tda10086_read_byte(state, 0x1d);
        if (tmp & 0x80)
                tmp |= 0xffffff00;
@@ -513,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
        fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
 
-       // the FEC
+       /* the FEC */
        val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
        switch(val) {
        case 0x00:
@@ -550,7 +555,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 val;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        val = tda10086_read_byte(state, 0x0e);
        *fe_status = 0;
@@ -566,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
                *fe_status |= FE_HAS_LOCK;
                if (!state->has_lock) {
                        state->has_lock = true;
-                       // modify parameters for stable reception
+                       /* modify parameters for stable reception */
                        tda10086_write_byte(state, 0x02, 0x00);
                }
        }
@@ -579,7 +584,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 _str;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        _str = 0xff - tda10086_read_byte(state, 0x43);
        *signal = (_str << 8) | _str;
@@ -592,7 +597,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
        struct tda10086_state* state = fe->demodulator_priv;
        u8 _snr;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        _snr = 0xff - tda10086_read_byte(state, 0x1c);
        *snr = (_snr << 8) | _snr;
@@ -604,12 +609,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // read it
+       /* read it */
        *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
 
-       // reset counter
+       /* reset counter */
        tda10086_write_byte(state, 0x18, 0x00);
        tda10086_write_byte(state, 0x18, 0x80);
 
@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
-       // read it
+       /* read it */
        *ber = 0;
        *ber |= tda10086_read_byte(state, 0x15);
        *ber |= tda10086_read_byte(state, 0x16) << 8;
@@ -635,7 +640,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        tda10086_write_mask(state, 0x00, 0x08, 0x08);
 
@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
        struct tda10086_state* state = fe->demodulator_priv;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        if (enable) {
                tda10086_write_mask(state, 0x00, 0x10, 0x10);
@@ -737,7 +742,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
 {
        struct tda10086_state *state;
 
-       dprintk ("%s\n", __FUNCTION__);
+       dprintk ("%s\n", __func__);
 
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
index eeceaeee78ffb8407171ee62cb2880f8cce5068d..61148c558d8d8eb1a8ec236e0a58b63e5063f6cb 100644 (file)
 #include <linux/dvb/frontend.h>
 #include <linux/firmware.h>
 
+enum tda10086_xtal {
+       TDA10086_XTAL_16M,
+       TDA10086_XTAL_4M
+};
+
 struct tda10086_config
 {
        /* the demodulator's i2c address */
@@ -36,6 +41,9 @@ struct tda10086_config
 
        /* do we need the diseqc signal with carrier? */
        u8 diseqc_tone;
+
+       /* frequency of the reference xtal */
+       enum tda10086_xtal xtal_freq;
 };
 
 #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
@@ -45,9 +53,9 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config
 static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
                                                   struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TDA10086
+#endif /* CONFIG_DVB_TDA10086 */
 
-#endif // TDA10086_H
+#endif /* TDA10086_H */
index bca57099061366badc9cc4fec3dc8dde982ca02f..e27a7620a32f20b2f68990bc968714b270e168eb 100644 (file)
@@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe)
        unsigned char buf = 0x00;
        int ret;
        struct i2c_msg msg[] = {
-               { .addr = priv->i2c_addr, .flags = 0,
+               { .addr = priv->i2c_props.addr, .flags = 0,
                  .buf = &buf, .len = 1 },
-               { .addr = priv->i2c_addr, .flags = I2C_M_RD,
+               { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
                  .buf = regs, .len = 16 }
        };
 
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* read all registers */
-       ret = i2c_transfer(priv->i2c_adap, msg, 2);
+       ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe)
        unsigned char buf = 0x00;
        int ret, i;
        struct i2c_msg msg[] = {
-               { .addr = priv->i2c_addr, .flags = 0,
+               { .addr = priv->i2c_props.addr, .flags = 0,
                  .buf = &buf, .len = 1 },
-               { .addr = priv->i2c_addr, .flags = I2C_M_RD,
+               { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
                  .buf = regdump, .len = TDA18271_NUM_REGS }
        };
 
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* read all registers */
-       ret = i2c_transfer(priv->i2c_adap, msg, 2);
+       ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
        unsigned char buf[TDA18271_NUM_REGS + 1];
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+       struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
                               .buf = buf, .len = len + 1 };
        int i, ret;
 
@@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
        tda18271_i2c_gate_ctrl(fe, 1);
 
        /* write registers */
-       ret = i2c_transfer(priv->i2c_adap, &msg, 1);
+       ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
 
        tda18271_i2c_gate_ctrl(fe, 0);
 
@@ -217,13 +217,29 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
 
 /*---------------------------------------------------------------------*/
 
+int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                               enum tda18271_pll pll, int force)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       unsigned char *regs = priv->tda18271_regs;
+
+       int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
+
+       regs[r_cp] &= ~0x20;
+       regs[r_cp] |= ((force & 1) << 5);
+       tda18271_write_regs(fe, r_cp, 1);
+
+       return 0;
+}
+
 int tda18271_init_regs(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
 
        tda_dbg("initializing registers for device @ %d-%04x\n",
-               i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
+               i2c_adapter_id(priv->i2c_props.adap),
+               priv->i2c_props.addr);
 
        /* initialize registers */
        switch (priv->id) {
@@ -310,7 +326,12 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_EB22] = 0x48;
        regs[R_EB23] = 0xb0;
 
-       tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+       if (priv->small_i2c) {
+               tda18271_write_regs(fe, 0x00, 0x10);
+               tda18271_write_regs(fe, 0x10, 0x10);
+               tda18271_write_regs(fe, 0x20, 0x07);
+       } else
+               tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
 
        /* setup agc1 gain */
        regs[R_EB17] = 0x00;
@@ -349,24 +370,15 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        regs[R_MD2] = 0x08;
        regs[R_MD3] = 0x00;
 
-       switch (priv->id) {
-       case TDA18271HDC1:
-               tda18271_write_regs(fe, R_EP3, 11);
-               break;
-       case TDA18271HDC2:
-               tda18271_write_regs(fe, R_EP3, 12);
-               break;
-       };
+       tda18271_write_regs(fe, R_EP3, 11);
 
        if ((priv->id) == TDA18271HDC2) {
                /* main pll cp source on */
-               regs[R_EB4] = 0x61;
-               tda18271_write_regs(fe, R_EB4, 1);
+               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
                msleep(1);
 
                /* main pll cp source off */
-               regs[R_EB4] = 0x41;
-               tda18271_write_regs(fe, R_EB4, 1);
+               tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
        }
 
        msleep(5); /* pll locking */
@@ -398,6 +410,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        tda18271_write_regs(fe, R_EP3, 11);
        msleep(5); /* pll locking */
 
+       /* launch detector */
        tda18271_write_regs(fe, R_EP1, 1);
        msleep(5); /* wanted mid measurement */
 
index dfe72aaec3802188f3f385d3171d80617c7d903e..b262100ae897db7b8806f89658c2bf9cad658e45 100644 (file)
@@ -31,30 +31,23 @@ static int tda18271_cal_on_startup;
 module_param_named(cal, tda18271_cal_on_startup, int, 0644);
 MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
 
-static LIST_HEAD(tda18271_list);
 static DEFINE_MUTEX(tda18271_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
 
 /*---------------------------------------------------------------------*/
 
-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
+static inline int charge_pump_source(struct dvb_frontend *fe, int force)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
-       unsigned char *regs = priv->tda18271_regs;
-
-       tda18271_read_regs(fe);
-
-       /* test IR_CAL_OK to see if we need init */
-       if ((regs[R_EP1] & 0x08) == 0)
-               tda18271_init_regs(fe);
-
-       return 0;
+       return tda18271_charge_pump_source(fe,
+                                          (priv->role == TDA18271_SLAVE) ?
+                                          TDA18271_CAL_PLL :
+                                          TDA18271_MAIN_PLL, force);
 }
 
-/* ------------------------------------------------------------------ */
-
 static int tda18271_channel_configuration(struct dvb_frontend *fe,
-                                         u32 ifc, u32 freq, u32 bw, u8 std,
-                                         int radio)
+                                         struct tda18271_std_map_item *map,
+                                         u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -64,38 +57,34 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* set standard */
        regs[R_EP3]  &= ~0x1f; /* clear std bits */
-       regs[R_EP3]  |= std;
+       regs[R_EP3]  |= (map->agc_mode << 3) | map->std;
+
+       /* set rfagc to high speed mode */
+       regs[R_EP3] &= ~0x04;
 
        /* set cal mode to normal */
        regs[R_EP4]  &= ~0x03;
 
        /* update IF output level & IF notch frequency */
        regs[R_EP4]  &= ~0x1c; /* clear if level bits */
+       regs[R_EP4]  |= (map->if_lvl << 2);
 
        switch (priv->mode) {
        case TDA18271_ANALOG:
                regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
                break;
        case TDA18271_DIGITAL:
-               regs[R_EP4]  |= 0x04; /* IF level = 1 */
                regs[R_MPD]  |= 0x80; /* IF notch = 1 */
                break;
        }
 
-       if (radio)
-               regs[R_EP4]  |=  0x80;
-       else
-               regs[R_EP4]  &= ~0x80;
+       /* update FM_RFn */
+       regs[R_EP4]  &= ~0x80;
+       regs[R_EP4]  |= map->fm_rfn << 7;
 
-       /* update RF_TOP / IF_TOP */
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_EB22]  = 0x2c;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EB22]  = 0x37;
-               break;
-       }
+       /* update rf top / if top */
+       regs[R_EB22]  = 0x00;
+       regs[R_EB22] |= map->rfagc_top;
        tda18271_write_regs(fe, R_EB22, 1);
 
        /* --------------------------------------------------------------- */
@@ -117,8 +106,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* dual tuner and agc1 extra configuration */
 
-       /* main vco when Master, cal vco when slave */
-       regs[R_EB1]  |= 0x04; /* FIXME: assumes master */
+       switch (priv->role) {
+       case TDA18271_MASTER:
+               regs[R_EB1]  |= 0x04; /* main vco */
+               break;
+       case TDA18271_SLAVE:
+               regs[R_EB1]  &= ~0x04; /* cal vco */
+               break;
+       }
 
        /* agc1 always active */
        regs[R_EB1]  &= ~0x02;
@@ -130,25 +125,40 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        /* --------------------------------------------------------------- */
 
-       N = freq + ifc;
+       N = map->if_freq * 1000 + freq;
 
-       /* FIXME: assumes master */
-       tda18271_calc_main_pll(fe, N);
-       tda18271_write_regs(fe, R_MPD, 4);
+       switch (priv->role) {
+       case TDA18271_MASTER:
+               tda18271_calc_main_pll(fe, N);
+               tda18271_write_regs(fe, R_MPD, 4);
+               break;
+       case TDA18271_SLAVE:
+               tda18271_calc_cal_pll(fe, N);
+               tda18271_write_regs(fe, R_CPD, 4);
+
+               regs[R_MPD] = regs[R_CPD] & 0x7f;
+               tda18271_write_regs(fe, R_MPD, 1);
+               break;
+       }
 
        tda18271_write_regs(fe, R_TM, 7);
 
-       /* main pll charge pump source */
-       regs[R_EB4] |= 0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       /* force charge pump source */
+       charge_pump_source(fe, 1);
 
        msleep(1);
 
-       /* normal operation for the main pll */
-       regs[R_EB4] &= ~0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       /* return pll to normal operation */
+       charge_pump_source(fe, 0);
 
-       msleep(5);
+       msleep(20);
+
+       /* set rfagc to normal speed mode */
+       if (map->fm_rfn)
+               regs[R_EP3] &= ~0x04;
+       else
+               regs[R_EP3] |= 0x04;
+       tda18271_write_regs(fe, R_EP3, 1);
 
        return 0;
 }
@@ -195,8 +205,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe)
        return tm;
 }
 
-static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe,
-                                                  u32 freq)
+/* ------------------------------------------------------------------ */
+
+static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
+                                                    u32 freq)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
@@ -296,12 +308,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        tda18271_write_regs(fe, R_EB13, 1);
 
        /* main pll charge pump source */
-       regs[R_EB4]  |= 0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
 
        /* cal pll charge pump source */
-       regs[R_EB7]  |= 0x20;
-       tda18271_write_regs(fe, R_EB7, 1);
+       tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
 
        /* force dcdc converter to 0 V */
        regs[R_EB14] = 0x00;
@@ -320,8 +330,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        /* set the internal calibration signal */
        N = freq;
 
-       tda18271_calc_main_pll(fe, N);
-       tda18271_write_regs(fe, R_MPD, 4);
+       tda18271_calc_cal_pll(fe, N);
+       tda18271_write_regs(fe, R_CPD, 4);
 
        /* downconvert internal calibration */
        N += 1000000;
@@ -339,14 +349,12 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
        /* --------------------------------------------------------------- */
 
        /* normal operation for the main pll */
-       regs[R_EB4] &= ~0x20;
-       tda18271_write_regs(fe, R_EB4, 1);
+       tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
 
        /* normal operation for the cal pll  */
-       regs[R_EB7] &= ~0x20;
-       tda18271_write_regs(fe, R_EB7, 1);
+       tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
 
-       msleep(5); /* plls locking */
+       msleep(10); /* plls locking */
 
        /* launch the rf tracking filters calibration */
        regs[R_EB20]  |= 0x20;
@@ -443,7 +451,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
 
                count += 200;
 
-               if (count < count_limit)
+               if (count <= count_limit)
                        continue;
 
                if (sgn <= 0)
@@ -587,7 +595,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
 
 /* ------------------------------------------------------------------ */
 
-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
+static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
@@ -610,63 +618,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int tda18271_init(struct dvb_frontend *fe)
-{
-       struct tda18271_priv *priv = fe->tuner_priv;
-
-       mutex_lock(&priv->lock);
-
-       /* power up */
-       tda18271_set_standby_mode(fe, 0, 0, 0);
-
-       /* initialization */
-       tda18271_ir_cal_init(fe);
-
-       if (priv->id == TDA18271HDC2)
-               tda18271_rf_cal_init(fe);
-
-       mutex_unlock(&priv->lock);
-
-       return 0;
-}
-
-static int tda18271c2_tune(struct dvb_frontend *fe,
-                          u32 ifc, u32 freq, u32 bw, u8 std, int radio)
-{
-       struct tda18271_priv *priv = fe->tuner_priv;
-
-       tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
-       tda18271_init(fe);
-
-       mutex_lock(&priv->lock);
-
-       tda18271_rf_tracking_filters_correction(fe, freq);
-
-       tda18271_channel_configuration(fe, ifc, freq, bw, std, radio);
-
-       mutex_unlock(&priv->lock);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271c1_tune(struct dvb_frontend *fe,
-                          u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
+                                                    u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
        u32 N = 0;
 
-       tda18271_init(fe);
-
-       mutex_lock(&priv->lock);
-
-       tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
-
-       /* RF tracking filter calibration */
-
        /* calculate bp filter */
        tda18271_calc_bp_filter(fe, &freq);
        tda18271_write_regs(fe, R_EP1, 1);
@@ -737,7 +695,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
 
        regs[R_EB7]   = 0x40;
        tda18271_write_regs(fe, R_EB7, 1);
-       msleep(10);
+       msleep(10); /* pll locking */
 
        regs[R_EB20]  = 0xec;
        tda18271_write_regs(fe, R_EB20, 1);
@@ -752,74 +710,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
        if (0 == tda18271_calc_rf_cal(fe, &freq))
                tda18271_write_regs(fe, R_EB14, 1);
 
-       /* Channel Configuration */
+       return 0;
+}
 
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_EB22]  = 0x2c;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EB22]  = 0x37;
-               break;
-       }
-       tda18271_write_regs(fe, R_EB22, 1);
+/* ------------------------------------------------------------------ */
 
-       regs[R_EP1]  |= 0x40; /* set dis power level on */
+static int tda18271_ir_cal_init(struct dvb_frontend *fe)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       unsigned char *regs = priv->tda18271_regs;
 
-       /* set standard */
-       regs[R_EP3]  &= ~0x1f; /* clear std bits */
+       tda18271_read_regs(fe);
 
-       /* see table 22 */
-       regs[R_EP3]  |= std;
+       /* test IR_CAL_OK to see if we need init */
+       if ((regs[R_EP1] & 0x08) == 0)
+               tda18271_init_regs(fe);
 
-       regs[R_EP4]  &= ~0x03; /* set cal mode to normal */
+       return 0;
+}
 
-       regs[R_EP4]  &= ~0x1c; /* clear if level bits */
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_EP4]  |= 0x04;
-               regs[R_MPD]  |= 0x80;
-               break;
-       }
+static int tda18271_init(struct dvb_frontend *fe)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
 
-       if (radio)
-               regs[R_EP4]  |=  0x80;
-       else
-               regs[R_EP4]  &= ~0x80;
+       mutex_lock(&priv->lock);
 
-       /* image rejection validity */
-       tda18271_calc_ir_measure(fe, &freq);
+       /* power up */
+       tda18271_set_standby_mode(fe, 0, 0, 0);
 
-       /* calculate MAIN PLL */
-       N = freq + ifc;
+       /* initialization */
+       tda18271_ir_cal_init(fe);
 
-       tda18271_calc_main_pll(fe, N);
+       if (priv->id == TDA18271HDC2)
+               tda18271c2_rf_cal_init(fe);
 
-       tda18271_write_regs(fe, R_TM, 15);
-       msleep(5);
        mutex_unlock(&priv->lock);
 
        return 0;
 }
 
-static inline int tda18271_tune(struct dvb_frontend *fe,
-                               u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+static int tda18271_tune(struct dvb_frontend *fe,
+                        struct tda18271_std_map_item *map, u32 freq, u32 bw)
 {
        struct tda18271_priv *priv = fe->tuner_priv;
-       int ret = -EINVAL;
+
+       tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
+               freq, map->if_freq, bw, map->agc_mode, map->std);
+
+       tda18271_init(fe);
+
+       mutex_lock(&priv->lock);
 
        switch (priv->id) {
        case TDA18271HDC1:
-               ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
+               tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
                break;
        case TDA18271HDC2:
-               ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
+               tda18271c2_rf_tracking_filters_correction(fe, freq);
                break;
        }
-       return ret;
+       tda18271_channel_configuration(fe, map, freq, bw);
+
+       mutex_unlock(&priv->lock);
+
+       return 0;
 }
 
 /* ------------------------------------------------------------------ */
@@ -829,9 +783,8 @@ static int tda18271_set_params(struct dvb_frontend *fe,
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_std_map *std_map = &priv->std;
+       struct tda18271_std_map_item *map;
        int ret;
-       u8 std;
-       u16 sgIF;
        u32 bw, freq = params->frequency;
 
        priv->mode = TDA18271_DIGITAL;
@@ -840,13 +793,11 @@ static int tda18271_set_params(struct dvb_frontend *fe,
                switch (params->u.vsb.modulation) {
                case VSB_8:
                case VSB_16:
-                       std  = std_map->atsc_6.std_bits;
-                       sgIF = std_map->atsc_6.if_freq;
+                       map = &std_map->atsc_6;
                        break;
                case QAM_64:
                case QAM_256:
-                       std  = std_map->qam_6.std_bits;
-                       sgIF = std_map->qam_6.if_freq;
+                       map = &std_map->qam_6;
                        break;
                default:
                        tda_warn("modulation not set!\n");
@@ -861,18 +812,15 @@ static int tda18271_set_params(struct dvb_frontend *fe,
                switch (params->u.ofdm.bandwidth) {
                case BANDWIDTH_6_MHZ:
                        bw = 6000000;
-                       std  = std_map->dvbt_6.std_bits;
-                       sgIF = std_map->dvbt_6.if_freq;
+                       map = &std_map->dvbt_6;
                        break;
                case BANDWIDTH_7_MHZ:
                        bw = 7000000;
-                       std  = std_map->dvbt_7.std_bits;
-                       sgIF = std_map->dvbt_7.if_freq;
+                       map = &std_map->dvbt_7;
                        break;
                case BANDWIDTH_8_MHZ:
                        bw = 8000000;
-                       std  = std_map->dvbt_8.std_bits;
-                       sgIF = std_map->dvbt_8.if_freq;
+                       map = &std_map->dvbt_8;
                        break;
                default:
                        tda_warn("bandwidth not set!\n");
@@ -887,7 +835,7 @@ static int tda18271_set_params(struct dvb_frontend *fe,
        if (fe->ops.analog_ops.standby)
                fe->ops.analog_ops.standby(fe);
 
-       ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
+       ret = tda18271_tune(fe, map, freq, bw);
 
        if (ret < 0)
                goto fail;
@@ -904,57 +852,46 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
 {
        struct tda18271_priv *priv = fe->tuner_priv;
        struct tda18271_std_map *std_map = &priv->std;
+       struct tda18271_std_map_item *map;
        char *mode;
-       int ret, radio = 0;
-       u8 std;
-       u16 sgIF;
+       int ret;
        u32 freq = params->frequency * 62500;
 
        priv->mode = TDA18271_ANALOG;
 
        if (params->mode == V4L2_TUNER_RADIO) {
-               radio = 1;
                freq = freq / 1000;
-               std  = std_map->fm_radio.std_bits;
-               sgIF = std_map->fm_radio.if_freq;
+               map = &std_map->fm_radio;
                mode = "fm";
        } else if (params->std & V4L2_STD_MN) {
-               std  = std_map->atv_mn.std_bits;
-               sgIF = std_map->atv_mn.if_freq;
+               map = &std_map->atv_mn;
                mode = "MN";
        } else if (params->std & V4L2_STD_B) {
-               std  = std_map->atv_b.std_bits;
-               sgIF = std_map->atv_b.if_freq;
+               map = &std_map->atv_b;
                mode = "B";
        } else if (params->std & V4L2_STD_GH) {
-               std  = std_map->atv_gh.std_bits;
-               sgIF = std_map->atv_gh.if_freq;
+               map = &std_map->atv_gh;
                mode = "GH";
        } else if (params->std & V4L2_STD_PAL_I) {
-               std  = std_map->atv_i.std_bits;
-               sgIF = std_map->atv_i.if_freq;
+               map = &std_map->atv_i;
                mode = "I";
        } else if (params->std & V4L2_STD_DK) {
-               std  = std_map->atv_dk.std_bits;
-               sgIF = std_map->atv_dk.if_freq;
+               map = &std_map->atv_dk;
                mode = "DK";
        } else if (params->std & V4L2_STD_SECAM_L) {
-               std  = std_map->atv_l.std_bits;
-               sgIF = std_map->atv_l.if_freq;
+               map = &std_map->atv_l;
                mode = "L";
        } else if (params->std & V4L2_STD_SECAM_LC) {
-               std  = std_map->atv_lc.std_bits;
-               sgIF = std_map->atv_lc.if_freq;
+               map = &std_map->atv_lc;
                mode = "L'";
        } else {
-               std  = std_map->atv_i.std_bits;
-               sgIF = std_map->atv_i.if_freq;
+               map = &std_map->atv_i;
                mode = "xx";
        }
 
        tda_dbg("setting tda18271 to system %s\n", mode);
 
-       ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
+       ret = tda18271_tune(fe, map, freq, 0);
 
        if (ret < 0)
                goto fail;
@@ -986,16 +923,9 @@ static int tda18271_release(struct dvb_frontend *fe)
 
        mutex_lock(&tda18271_list_mutex);
 
-       priv->count--;
+       if (priv)
+               hybrid_tuner_release_state(priv);
 
-       if (!priv->count) {
-               tda_dbg("destroying instance @ %d-%04x\n",
-                       i2c_adapter_id(priv->i2c_adap),
-                       priv->i2c_addr);
-               list_del(&priv->tda18271_list);
-
-               kfree(priv);
-       }
        mutex_unlock(&tda18271_list_mutex);
 
        fe->tuner_priv = NULL;
@@ -1020,15 +950,20 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 /* ------------------------------------------------------------------ */
 
 #define tda18271_update_std(std_cfg, name) do {                                \
-       if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) {         \
+       if (map->std_cfg.if_freq +                                      \
+               map->std_cfg.agc_mode + map->std_cfg.std +              \
+               map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) {     \
                tda_dbg("Using custom std config for %s\n", name);      \
                memcpy(&std->std_cfg, &map->std_cfg,                    \
                        sizeof(struct tda18271_std_map_item));          \
        } } while (0)
 
 #define tda18271_dump_std_item(std_cfg, name) do {                     \
-       tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n",               \
-               name, std->std_cfg.if_freq, std->std_cfg.std_bits);     \
+       tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, "          \
+               "if_lvl = %d, rfagc_top = 0x%02x\n",                    \
+               name, std->std_cfg.if_freq,                             \
+               std->std_cfg.agc_mode, std->std_cfg.std,                \
+               std->std_cfg.if_lvl, std->std_cfg.rfagc_top);           \
        } while (0)
 
 static int tda18271_dump_std_map(struct dvb_frontend *fe)
@@ -1037,20 +972,20 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe)
        struct tda18271_std_map *std = &priv->std;
 
        tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
-       tda18271_dump_std_item(fm_radio, "fm");
-       tda18271_dump_std_item(atv_b,  "pal b");
-       tda18271_dump_std_item(atv_dk, "pal dk");
-       tda18271_dump_std_item(atv_gh, "pal gh");
-       tda18271_dump_std_item(atv_i,  "pal i");
-       tda18271_dump_std_item(atv_l,  "pal l");
-       tda18271_dump_std_item(atv_lc, "pal l'");
+       tda18271_dump_std_item(fm_radio, "  fm  ");
+       tda18271_dump_std_item(atv_b,  "atv b ");
+       tda18271_dump_std_item(atv_dk, "atv dk");
+       tda18271_dump_std_item(atv_gh, "atv gh");
+       tda18271_dump_std_item(atv_i,  "atv i ");
+       tda18271_dump_std_item(atv_l,  "atv l ");
+       tda18271_dump_std_item(atv_lc, "atv l'");
        tda18271_dump_std_item(atv_mn, "atv mn");
        tda18271_dump_std_item(atsc_6, "atsc 6");
        tda18271_dump_std_item(dvbt_6, "dvbt 6");
        tda18271_dump_std_item(dvbt_7, "dvbt 7");
        tda18271_dump_std_item(dvbt_8, "dvbt 8");
-       tda18271_dump_std_item(qam_6,  "qam 6");
-       tda18271_dump_std_item(qam_8,  "qam 8");
+       tda18271_dump_std_item(qam_6,  "qam 6 ");
+       tda18271_dump_std_item(qam_8,  "qam 8 ");
 
        return 0;
 }
@@ -1109,7 +1044,8 @@ static int tda18271_get_id(struct dvb_frontend *fe)
        }
 
        tda_info("%s detected @ %d-%04x%s\n", name,
-                i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
+                i2c_adapter_id(priv->i2c_props.adap),
+                priv->i2c_props.addr,
                 (0 == ret) ? "" : ", device not supported.");
 
        return ret;
@@ -1136,45 +1072,28 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                                     struct tda18271_config *cfg)
 {
        struct tda18271_priv *priv = NULL;
-       int state_found = 0;
+       int instance;
 
        mutex_lock(&tda18271_list_mutex);
 
-       list_for_each_entry(priv, &tda18271_list, tda18271_list) {
-               if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
-                   (priv->i2c_addr == addr)) {
-                       tda_dbg("attaching existing tuner @ %d-%04x\n",
-                               i2c_adapter_id(priv->i2c_adap),
-                               priv->i2c_addr);
-                       priv->count++;
-                       fe->tuner_priv = priv;
-                       state_found = 1;
-                       /* allow dvb driver to override i2c gate setting */
-                       if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
-                               priv->gate = cfg->gate;
-                       break;
-               }
-       }
-       if (state_found == 0) {
-               tda_dbg("creating new tuner instance @ %d-%04x\n",
-                       i2c_adapter_id(i2c), addr);
-
-               priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
-               if (priv == NULL) {
-                       mutex_unlock(&tda18271_list_mutex);
-                       return NULL;
-               }
-
-               priv->i2c_addr = addr;
-               priv->i2c_adap = i2c;
+       instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c, addr, "tda18271");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
                priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
+               priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
                priv->cal_initialized = false;
                mutex_init(&priv->lock);
-               priv->count++;
 
                fe->tuner_priv = priv;
 
-               list_add_tail(&priv->tda18271_list, &tda18271_list);
+               if (cfg)
+                       priv->small_i2c = cfg->small_i2c;
 
                if (tda18271_get_id(fe) < 0)
                        goto fail;
@@ -1186,9 +1105,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                tda18271_init_regs(fe);
 
                if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
-                       tda18271_rf_cal_init(fe);
+                       tda18271c2_rf_cal_init(fe);
 
                mutex_unlock(&priv->lock);
+               break;
+       default:
+               /* existing tuner instance */
+               fe->tuner_priv = priv;
+
+               /* allow dvb driver to override i2c gate setting */
+               if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+                       priv->gate = cfg->gate;
+               break;
        }
 
        /* override default std map with values in config struct */
@@ -1200,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
        memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
               sizeof(struct dvb_tuner_ops));
 
-       if (tda18271_debug & DBG_MAP)
+       if (tda18271_debug & (DBG_MAP | DBG_ADV))
                tda18271_dump_std_map(fe);
 
        return fe;
@@ -1214,7 +1142,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach);
 MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 7b939a5325fb970189feeb998913f37e49d11e19..2bc5eb368ea2853109298eb7bf1a7ee4e4b4625b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
+#include "tuner-i2c.h"
 #include "tda18271.h"
 
 #define R_ID     0x00  /* ID byte                */
@@ -85,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal {
        int rf_b2;
 };
 
+enum tda18271_pll {
+       TDA18271_MAIN_PLL,
+       TDA18271_CAL_PLL,
+};
+
 enum tda18271_mode {
        TDA18271_ANALOG,
        TDA18271_DIGITAL,
@@ -98,19 +104,19 @@ enum tda18271_ver {
 };
 
 struct tda18271_priv {
-       u8 i2c_addr;
-       struct i2c_adapter *i2c_adap;
        unsigned char tda18271_regs[TDA18271_NUM_REGS];
 
-       struct list_head tda18271_list;
+       struct list_head        hybrid_tuner_instance_list;
+       struct tuner_i2c_props  i2c_props;
 
        enum tda18271_mode mode;
+       enum tda18271_role role;
        enum tda18271_i2c_gate gate;
        enum tda18271_ver id;
 
-       unsigned int count;
        unsigned int tm_rfcal;
        unsigned int cal_initialized:1;
+       unsigned int small_i2c:1;
 
        struct tda18271_map_layout *maps;
        struct tda18271_std_map std;
@@ -133,7 +139,7 @@ extern int tda18271_debug;
 #define DBG_CAL  16
 
 #define tda_printk(kern, fmt, arg...) \
-       printk(kern "%s: " fmt, __FUNCTION__, ##arg)
+       printk(kern "%s: " fmt, __func__, ##arg)
 
 #define dprintk(kern, lvl, fmt, arg...) do {\
        if (tda18271_debug & lvl) \
@@ -188,6 +194,8 @@ extern int tda18271_read_extended(struct dvb_frontend *fe);
 extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
 extern int tda18271_init_regs(struct dvb_frontend *fe);
 
+extern int tda18271_charge_pump_source(struct dvb_frontend *fe,
+                                      enum tda18271_pll pll, int force);
 extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
                                     int sm, int sm_lt, int sm_xt);
 
index e94afcfdc5bce96fbae91878560fbdabcd830510..83e7561960c185aa7e92a43739bd22ae169677fd 100644 (file)
@@ -1187,37 +1187,65 @@ fail:
 /*---------------------------------------------------------------------*/
 
 static struct tda18271_std_map tda18271c1_std_map = {
-       .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
-       .atv_b    = { .if_freq = 6750, .std_bits = 0x0e },
-       .atv_dk   = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_gh   = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_i    = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_l    = { .if_freq = 7750, .std_bits = 0x0f },
-       .atv_lc   = { .if_freq = 1250, .std_bits = 0x0f },
-       .atv_mn   = { .if_freq = 5750, .std_bits = 0x0d },
-       .atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
-       .dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
-       .dvbt_7   = { .if_freq = 3800, .std_bits = 0x1d },
-       .dvbt_8   = { .if_freq = 4300, .std_bits = 0x1e },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
+       .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
+       .atv_b    = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_dk   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_gh   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_i    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_l    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
+       .atv_mn   = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
+       .atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_7   = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .dvbt_8   = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
+       .qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
 
 static struct tda18271_std_map tda18271c2_std_map = {
-       .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
-       .atv_b    = { .if_freq = 6000, .std_bits = 0x0d },
-       .atv_dk   = { .if_freq = 6900, .std_bits = 0x0e },
-       .atv_gh   = { .if_freq = 7100, .std_bits = 0x0e },
-       .atv_i    = { .if_freq = 7250, .std_bits = 0x0e },
-       .atv_l    = { .if_freq = 6900, .std_bits = 0x0e },
-       .atv_lc   = { .if_freq = 1250, .std_bits = 0x0e },
-       .atv_mn   = { .if_freq = 5400, .std_bits = 0x0c },
-       .atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
-       .dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
-       .dvbt_7   = { .if_freq = 3500, .std_bits = 0x1c },
-       .dvbt_8   = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
-       .qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
+       .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
+       .atv_b    = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
+       .atv_dk   = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_gh   = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_i    = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_l    = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
+       .atv_mn   = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4,
+                     .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */
+       .atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_7   = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
+       .dvbt_8   = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+       .qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
+                     .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
 };
 
 /*---------------------------------------------------------------------*/
index 24b0e35a2ab3c7ae3b3134af19895ba4220407eb..0e7af8d05a38cb91c074b7310bad34b93ad33073 100644 (file)
 
 struct tda18271_std_map_item {
        u16 if_freq;
-       u8 std_bits;
+
+       /* EP3[4:3] */
+       unsigned int agc_mode:2;
+       /* EP3[2:0] */
+       unsigned int std:3;
+       /* EP4[7] */
+       unsigned int fm_rfn:1;
+       /* EP4[4:2] */
+       unsigned int if_lvl:3;
+       /* EB22[6:0] */
+       unsigned int rfagc_top:7;
 };
 
 struct tda18271_std_map {
@@ -46,6 +56,11 @@ struct tda18271_std_map {
        struct tda18271_std_map_item qam_8;
 };
 
+enum tda18271_role {
+       TDA18271_MASTER = 0,
+       TDA18271_SLAVE,
+};
+
 enum tda18271_i2c_gate {
        TDA18271_GATE_AUTO = 0,
        TDA18271_GATE_ANALOG,
@@ -56,8 +71,14 @@ struct tda18271_config {
        /* override default if freq / std settings (optional) */
        struct tda18271_std_map *std_map;
 
+       /* master / slave tuner: master uses main pll, slave uses cal pll */
+       enum tda18271_role role;
+
        /* use i2c gate provided by analog or digital demod */
        enum tda18271_i2c_gate gate;
+
+       /* some i2c providers cant write all 39 registers at once */
+       unsigned int small_i2c:1;
 };
 
 #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
@@ -70,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter *i2c,
                                                   struct tda18271_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 011b74f798a031207fbe71eb7313c106b377bf73..5b843b2e67e874c03f79cdfb1407680e16ee99ad 100644 (file)
@@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
 
        if (ret != 1)
                dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
-                       __FUNCTION__, reg, ret);
+                       __func__, reg, ret);
 
        return (ret != 1) ? -1 : 0;
 }
@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
 
        if (ret != 2)
                dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
-                       __FUNCTION__, reg1, ret);
+                       __func__, reg1, ret);
 
        return ret == 2 ? 0 : -1;
 }
index 2d3307999f21cf3b47674de73586e55f769405bb..5a03c14a10e80fc4f0276347b5003b78f411f95c 100644 (file)
@@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
 static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA8083
index bd3ebc2848352b75301f08d6bcafd771ec629564..a051554b5e2589aeb32060ebb0a41c1c38b65e84 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "tda826x.h"
 
-static int debug = 0;
+static int debug;
 #define dprintk(args...) \
        do { \
                if (debug) printk(KERN_DEBUG "tda826x: " args); \
@@ -54,7 +54,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
        u8 buf [] = { 0x00, 0x8d };
        struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        if (!priv->has_loopthrough)
                buf[1] = 0xad;
@@ -62,7 +62,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               dprintk("%s: i2c error\n", __FUNCTION__);
+               dprintk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
@@ -75,13 +75,24 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        struct tda826x_priv *priv = fe->tuner_priv;
        int ret;
        u32 div;
+       u32 ksyms;
+       u32 bandwidth;
        u8 buf [11];
        struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        div = (params->frequency + (1000-1)) / 1000;
 
+       /* BW = ((1 + RO) * SR/2 + 5) * 1.3      [SR in MSPS, BW in MHz] */
+       /* with R0 = 0.35 and some transformations: */
+       ksyms = params->u.qpsk.symbol_rate / 1000;
+       bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
+       if (bandwidth < 5)
+               bandwidth = 5;
+       else if (bandwidth > 36)
+               bandwidth = 36;
+
        buf[0] = 0x00; // subaddress
        buf[1] = 0x09; // powerdown RSSI + the magic value 1
        if (!priv->has_loopthrough)
@@ -89,7 +100,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
        buf[3] = div >> 7;
        buf[4] = div << 1;
-       buf[5] = 0x77; // baseband cut-off 19 MHz
+       buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
        buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
        buf[7] = 0x83; // charge pumps at high, tests off
        buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
@@ -99,7 +110,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               dprintk("%s: i2c error\n", __FUNCTION__);
+               dprintk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
@@ -138,7 +149,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
        };
        int ret;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
index ad998119596183264e0ef9b06907e377a73dff3e..89e97926ab23acb4dcd78f7537d9988d4b62ce16 100644 (file)
@@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c,
                                                  int has_loopthrough)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA826X
index 229b11987a589fed652c00934c91101f59867eeb..d30d2c9094d9b0fcdde74cd3212d9f5cbd700b95 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tda827x.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
@@ -142,7 +142,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
        int i, tuner_freq, if_freq;
        u32 N;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        switch (params->u.ofdm.bandwidth) {
        case BANDWIDTH_6_MHZ:
                if_freq = 4000000;
@@ -186,7 +186,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not write to tuner at addr: 0x%02x\n",
-                      __FUNCTION__, priv->i2c_addr << 1);
+                      __func__, priv->i2c_addr << 1);
                return -EIO;
        }
        msleep(500);
@@ -212,7 +212,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
        struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
                               .buf = buf, .len = sizeof(buf) };
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(priv->i2c_adap, &msg, 1);
@@ -389,6 +389,79 @@ static struct tda827xa_data tda827xa_analog[] = {
        { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
 };
 
+static int tda827xa_sleep(struct dvb_frontend *fe)
+{
+       struct tda827x_priv *priv = fe->tuner_priv;
+       static u8 buf[] = { 0x30, 0x90 };
+       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+
+       dprintk("%s:\n", __func__);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       i2c_transfer(priv->i2c_adap, &msg, 1);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (priv->cfg && priv->cfg->sleep)
+               priv->cfg->sleep(fe);
+
+       return 0;
+}
+
+static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
+                             struct analog_parameters *params)
+{
+       struct tda827x_priv *priv = fe->tuner_priv;
+       unsigned char buf[] = {0x22, 0x01};
+       int arg;
+       int gp_func;
+       struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+
+       if (NULL == priv->cfg) {
+               dprintk("tda827x_config not defined, cannot set LNA gain!\n");
+               return;
+       }
+       if (priv->cfg->config) {
+               if (high)
+                       dprintk("setting LNA to high gain\n");
+               else
+                       dprintk("setting LNA to low gain\n");
+       }
+       switch (priv->cfg->config) {
+       case 0: /* no LNA */
+               break;
+       case 1: /* switch is GPIO 0 of tda8290 */
+       case 2:
+               if (params == NULL) {
+                       gp_func = 0;
+                       arg  = 0;
+               } else {
+                       /* turn Vsync on */
+                       gp_func = 1;
+                       if (params->std & V4L2_STD_MN)
+                               arg = 1;
+                       else
+                               arg = 0;
+               }
+               if (priv->cfg->tuner_callback)
+                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+                                                               gp_func, arg);
+               buf[1] = high ? 0 : 1;
+               if (priv->cfg->config == 2)
+                       buf[1] = high ? 1 : 0;
+               i2c_transfer(priv->i2c_adap, &msg, 1);
+               break;
+       case 3: /* switch with GPIO of saa713x */
+               if (priv->cfg->tuner_callback)
+                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
+               break;
+       }
+}
+
 static int tda827xa_set_params(struct dvb_frontend *fe,
                               struct dvb_frontend_parameters *params)
 {
@@ -401,9 +474,9 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        int i, tuner_freq, if_freq;
        u32 N;
 
-       dprintk("%s:\n", __FUNCTION__);
-       if (priv->cfg && priv->cfg->lna_gain)
-               priv->cfg->lna_gain(fe, 1);
+       dprintk("%s:\n", __func__);
+
+       tda827xa_lna_gain(fe, 1, NULL);
        msleep(20);
 
        switch (params->u.ofdm.bandwidth) {
@@ -444,7 +517,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not write to tuner at addr: 0x%02x\n",
-                      __FUNCTION__, priv->i2c_addr << 1);
+                      __func__, priv->i2c_addr << 1);
                return -EIO;
        }
        buf[0] = 0x90;
@@ -474,8 +547,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        buf[1] >>= 4;
        dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
        if ((buf[1]) < 2) {
-               if (priv->cfg && priv->cfg->lna_gain)
-                       priv->cfg->lna_gain(fe, 0);
+               tda827xa_lna_gain(fe, 0, NULL);
                buf[0] = 0x60;
                buf[1] = 0x0c;
                if (fe->ops.i2c_gate_ctrl)
@@ -523,75 +595,6 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
        return 0;
 }
 
-static int tda827xa_sleep(struct dvb_frontend *fe)
-{
-       struct tda827x_priv *priv = fe->tuner_priv;
-       static u8 buf[] = { 0x30, 0x90 };
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-                              .buf = buf, .len = sizeof(buf) };
-
-       dprintk("%s:\n", __FUNCTION__);
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-
-       i2c_transfer(priv->i2c_adap, &msg, 1);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
-
-       if (priv->cfg && priv->cfg->sleep)
-               priv->cfg->sleep(fe);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
-                             struct analog_parameters *params)
-{
-       struct tda827x_priv *priv = fe->tuner_priv;
-       unsigned char buf[] = {0x22, 0x01};
-       int arg;
-       struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-                              .buf = buf, .len = sizeof(buf) };
-
-       if (NULL == priv->cfg) {
-               dprintk("tda827x_config not defined, cannot set LNA gain!\n");
-               return;
-       }
-
-       if (priv->cfg->config) {
-               if (high)
-                       dprintk("setting LNA to high gain\n");
-               else
-                       dprintk("setting LNA to low gain\n");
-       }
-       switch (*priv->cfg->config) {
-       case 0: /* no LNA */
-               break;
-       case 1: /* switch is GPIO 0 of tda8290 */
-       case 2:
-               /* turn Vsync on */
-               if (params->std & V4L2_STD_MN)
-                       arg = 1;
-               else
-                       arg = 0;
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
-                                                 1, arg);
-               buf[1] = high ? 0 : 1;
-               if (*priv->cfg->config == 2)
-                       buf[1] = high ? 1 : 0;
-               i2c_transfer(priv->i2c_adap, &msg, 1);
-               break;
-       case 3: /* switch with GPIO of saa713x */
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
-                                                 0, high);
-               break;
-       }
-}
 
 static int tda827xa_set_analog_params(struct dvb_frontend *fe,
                                      struct analog_parameters *params)
@@ -726,7 +729,7 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 static int tda827x_init(struct dvb_frontend *fe)
 {
        struct tda827x_priv *priv = fe->tuner_priv;
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        if (priv->cfg && priv->cfg->init)
                priv->cfg->init(fe);
 
@@ -794,7 +797,7 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
                printk("%s: could not read from tuner at addr: 0x%02x\n",
-                      __FUNCTION__, msg.addr << 1);
+                      __func__, msg.addr << 1);
                return -EIO;
        }
        if ((data & 0x3c) == 0) {
@@ -818,7 +821,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
 {
        struct tda827x_priv *priv = NULL;
 
-       dprintk("%s:\n", __FUNCTION__);
+       dprintk("%s:\n", __func__);
        priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
        if (priv == NULL)
                return NULL;
index 92eb65b4012b37dcb28abb204f132ac34d8b1c29..b73c23570dab67e094482ebf31b77dcea29d4fe3 100644 (file)
 struct tda827x_config
 {
        /* saa7134 - provided callbacks */
-       void (*lna_gain) (struct dvb_frontend *fe, int high);
        int (*init) (struct dvb_frontend *fe);
        int (*sleep) (struct dvb_frontend *fe);
 
        /* interface to tda829x driver */
-       unsigned int *config;
+       unsigned int config;
+       int          switch_addr;
        int (*tuner_callback) (void *dev, int command, int arg);
 
        void (*agcf)(struct dvb_frontend *fe);
@@ -61,7 +61,7 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c,
                                                  struct tda827x_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TDA827X
index 6ba0029dcf2eee56e93315d10f089a47772f5a3d..1790baee014c4c7cb0f1f3cdf749d386d978ebbc 100644 (file)
@@ -58,7 +58,7 @@ static int tua6100_sleep(struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-               printk("%s: i2c error\n", __FUNCTION__);
+               printk("%s: i2c error\n", __func__);
        }
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
index 03a665e7df6d733b2067650ca394ee9640280eaf..f83dbd5e42ae642dff9410681d1a114d08a17a3e 100644 (file)
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st
 #else
 static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUA6100
index 8791701c8f25c8a9288d842ae865c4ba6bd656aa..a184597f1d9be0002b8f567b245a849abef6553c 100644 (file)
@@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
 
        if (ret != 1)
                printk("ves1820: %s(): writereg error (reg == 0x%02x, "
-                       "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
+                       "val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
 
        return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
 
        if (ret != 2)
                printk("ves1820: %s(): readreg error (reg == 0x%02x, "
-               "ret == %i)\n", __FUNCTION__, reg, ret);
+               "ret == %i)\n", __func__, reg, ret);
 
        return b1[0];
 }
index e4a2a324046af986ac35c41a256ccdba3001408e..e902ed634ec301ea3ffe59fc3a5e0400a438cd4f 100644 (file)
@@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
 static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
                                           struct i2c_adapter* i2c, u8 pwm)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_VES1820
index 23fd0303c91b486a38776ab80fc8c915a0e9d364..bd558960bd87222eed8a71e7f696554e461ea9be 100644 (file)
@@ -48,7 +48,7 @@ struct ves1x93_state {
        u8 demod_type;
 };
 
-static int debug = 0;
+static int debug;
 #define dprintk        if (debug) printk
 
 #define DEMOD_VES1893          0
@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
        int err;
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
                return -EREMOTEIO;
        }
 
@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
        u32 tmp;
        u32 FIN;
 
-       dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
+       dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
 
        if (srate > state->config->xin/2)
                srate = state->config->xin/2;
@@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
        int i;
        int val;
 
-       dprintk("%s: init chip\n", __FUNCTION__);
+       dprintk("%s: init chip\n", __func__);
 
        for (i = 0; i < state->tab_size; i++) {
                if (state->init_1x93_wtab[i]) {
index d507f8966f816fb2aa4cff8222e2be2ab011cd46..8a5a49e808f63a152298e1b8f58247cdd0249e63 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
 static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
                                           struct i2c_adapter* i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_VES1X93
index f642ca200b596096c2f85167faeeeef4ec6b091f..43d35bdb221f0ab367953d557d9c29d4fae2b077 100644 (file)
@@ -151,7 +151,7 @@ typedef struct {
 #define FM_Radio_INPUT2        21
 #define FM_Radio_INPUT1        22
 
-XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
        {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
        {"M/N-NTSC/PAL-A2",   0x0600, 0x8020},
        {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
@@ -209,7 +209,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (priv->cfg->tuner_callback) {
                ret = priv->cfg->tuner_callback(priv->cfg->priv,
@@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
 
 static int xc_initialize(struct xc5000_priv *priv)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return xc_write_reg(priv, XREG_INIT, 0);
 }
 
@@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
        u16 VideoMode, u16 AudioMode)
 {
        int ret;
-       dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
+       dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
        dprintk(1, "%s() Standard = %s\n",
-               __FUNCTION__,
+               __func__,
                XC5000_Standard[priv->video_standard].Name);
 
        ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
@@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv)
 
 static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
 {
-       dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
+       dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
                rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
 
        if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
@@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
                rf_mode = XC_RF_MODE_CABLE;
                printk(KERN_ERR
                        "%s(), Invalid mode, defaulting to CABLE",
-                       __FUNCTION__);
+                       __func__);
        }
        return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
 }
@@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
 {
        u16 freq_code;
 
-       dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
 
        if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
                (freq_hz < xc5000_tuner_ops.info.frequency_min))
@@ -396,7 +396,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
 {
        u32 freq_code = (freq_khz * 1024)/1000;
        dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
-               __FUNCTION__, freq_khz, freq_code);
+               __func__, freq_khz, freq_code);
 
        return xc_write_reg(priv, XREG_IF_OUT, freq_code);
 }
@@ -488,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
 {
        int found = 0;
 
-       dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+       dprintk(1, "%s(%u)\n", __func__, freq_hz);
 
        if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
                return 0;
@@ -627,12 +627,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
+       dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
        switch(params->u.vsb.modulation) {
        case VSB_8:
        case VSB_16:
-               dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
+               dprintk(1, "%s() VSB modulation\n", __func__);
                priv->rf_mode = XC_RF_MODE_AIR;
                priv->freq_hz = params->frequency - 1750000;
                priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -641,7 +641,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        case QAM_64:
        case QAM_256:
        case QAM_AUTO:
-               dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
+               dprintk(1, "%s() QAM modulation\n", __func__);
                priv->rf_mode = XC_RF_MODE_CABLE;
                priv->freq_hz = params->frequency - 1750000;
                priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -652,7 +652,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        }
 
        dprintk(1, "%s() frequency=%d (compensated)\n",
-               __FUNCTION__, priv->freq_hz);
+               __func__, priv->freq_hz);
 
        ret = xc_SetSignalSource(priv, priv->rf_mode);
        if (ret != XC_RESULT_SUCCESS) {
@@ -697,7 +697,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
                xc_load_fw_and_init_tuner(fe);
 
        dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
-               __FUNCTION__, params->frequency);
+               __func__, params->frequency);
 
        priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
 
@@ -775,7 +775,7 @@ tune_channel:
 static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        *freq = priv->freq_hz;
        return 0;
 }
@@ -783,7 +783,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        *bw = priv->bandwidth;
        return 0;
@@ -796,7 +796,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
 
        xc_get_lock_status(priv, &lock_status);
 
-       dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
+       dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
 
        *status = lock_status;
 
@@ -836,7 +836,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
         * once shutdown without reloading the driver. Maybe I am not
@@ -848,7 +848,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
        if(ret != XC_RESULT_SUCCESS) {
                printk(KERN_ERR
                        "xc5000: %s() unable to shutdown tuner\n",
-                       __FUNCTION__);
+                       __func__);
                return -EREMOTEIO;
        }
        else {
@@ -860,7 +860,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
 static int xc5000_init(struct dvb_frontend *fe)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
                printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
@@ -875,7 +875,7 @@ static int xc5000_init(struct dvb_frontend *fe)
 
 static int xc5000_release(struct dvb_frontend *fe)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
        return 0;
@@ -907,7 +907,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
        struct xc5000_priv *priv = NULL;
        u16 id = 0;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
        if (priv == NULL)
index 32a5f1c86a16d699eb9fb116aaaf2548462613e8..b890883a0cdc224a8f888000564b7eb4f63635bc 100644 (file)
@@ -55,7 +55,7 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
                                                 struct i2c_adapter *i2c,
                                                 struct xc5000_config *cfg)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif // CONFIG_DVB_TUNER_XC5000
index 276e3b631dc211eedaf9612af4d48a5b04a84a80..36a5a1c101d5b91386a23796959857cabcd632df 100644 (file)
@@ -46,7 +46,7 @@ static int debug;
                if (debug) printk(KERN_DEBUG "zl10353: " args); \
        } while (0)
 
-static int debug_regs = 0;
+static int debug_regs;
 
 static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
 {
@@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
 
        if (ret != 2) {
                printk("%s: readreg error (reg=%d, ret==%i)\n",
-                      __FUNCTION__, reg, ret);
+                      __func__, reg, ret);
                return ret;
        }
 
@@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
        *nominal_rate = value;
 
        dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-               __FUNCTION__, bw, adc_clock, *nominal_rate);
+               __func__, bw, adc_clock, *nominal_rate);
 }
 
 static void zl10353_calc_input_freq(struct dvb_frontend *fe,
@@ -181,7 +181,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
        *input_freq = -value;
 
        dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-               __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
+               __func__, if2, ife, adc_clock, -(int)value, *input_freq);
 }
 
 static int zl10353_sleep(struct dvb_frontend *fe)
index fc734c22b5fa9d8231aa723698eb43746ba1d290..fdbb88ff75fe80eebba27d7c94c67022c84e9f30 100644 (file)
@@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
 static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
                                           struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_ZL10353 */
index 08a2599ed74a7463293ae0e8858642fd6b495d84..960ed5763ae1300f929538210bdbb509d36c4be0 100644 (file)
@@ -39,6 +39,8 @@
 #include "dvbdev.h"
 #include "tda1004x.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define DRIVER_NAME            "pluto2"
 
 #define REG_PIDn(n)            ((n) << 2)      /* PID n pattern registers */
@@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
                goto err_pluto_hw_exit;
 
        /* dvb */
-       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
+       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
+                                  THIS_MODULE, &pdev->dev, adapter_nr);
        if (ret < 0)
                goto err_i2c_del_adapter;
 
index 0e5701bdff19472bd08ec89a6b3219f9f634310e..747e7f1a6267be0a9d3d9cf4eb1d4766c97691b5 100644 (file)
@@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14:
 module_param(tv_standard, int, 0444);
 MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static void restart_feeds(struct av7110 *av7110);
 
 static int av7110_num;
@@ -359,7 +361,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
 {
        dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
        if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
                return;
        }
 
@@ -497,7 +499,7 @@ static void gpioirq(unsigned long data)
                       saa7146_read(av7110->dev, SSR));
 
        if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+               printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
                BUG(); /* maybe we should try resetting the debi? */
        }
 
@@ -827,7 +829,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        if (ret != 0 || handle >= 32) {
                printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
                                "ret %d  handle %04x\n",
-                               __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
+                               __func__, buf[0], buf[1], buf[2], buf[3],
                                ret, handle);
                dvbdmxfilter->hw_handle = 0xffff;
                if (!ret)
@@ -854,7 +856,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        handle = dvbdmxfilter->hw_handle;
        if (handle >= 32) {
                printk("%s tried to stop invalid filter %04x, filter type = %x\n",
-                               __FUNCTION__, handle, dvbdmxfilter->type);
+                               __func__, handle, dvbdmxfilter->type);
                return -EINVAL;
        }
 
@@ -867,7 +869,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        if (ret != 0 || answ[1] != handle) {
                printk("dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  "
                                "resp %04x %04x  pid %d\n",
-                               __FUNCTION__, buf[0], buf[1], buf[2], ret,
+                               __func__, buf[0], buf[1], buf[2], ret,
                                answ[0], answ[1], dvbdmxfilter->feed->pid);
                if (!ret)
                        ret = -1;
@@ -1122,7 +1124,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
 
        ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
        if (ret) {
-               printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
+               printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
                return ret;
        }
        dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
@@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                goto err_kfree_0;
 
        ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-                                  THIS_MODULE, &dev->pci->dev);
+                                  THIS_MODULE, &dev->pci->dev, adapter_nr);
        if (ret < 0)
                goto err_put_firmware_1;
 
index 39fbf7d5cffbca70e6abcada285ec0d176147783..e494e04eeee8fb7b8ac2922cbfb8e90d4e0c211c 100644 (file)
@@ -40,7 +40,7 @@
 extern int av7110_debug;
 
 #define dprintk(level,args...) \
-           do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
+           do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
 
 #define MAXFILT 32
 
index a468aa2e485475ba5583765b0e643781943f4ae1..9d81074b31dfe7b2b3ca105234f3d518c2c8d3d8 100644 (file)
@@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
        struct saa7146_dev *dev = av7110->dev;
 
        if (count <= 0 || count > 32764) {
-               printk("%s: invalid count %d\n", __FUNCTION__, count);
+               printk("%s: invalid count %d\n", __func__, count);
                return -1;
        }
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done failed\n", __func__);
                return -1;
        }
        saa7146_write(dev, DEBI_CONFIG, config);
@@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
        u32 result = 0;
 
        if (count > 32764 || count <= 0) {
-               printk("%s: invalid count %d\n", __FUNCTION__, count);
+               printk("%s: invalid count %d\n", __func__, count);
                return 0;
        }
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done #1 failed\n", __func__);
                return 0;
        }
        saa7146_write(dev, DEBI_AD, av7110->debi_bus);
@@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
        if (count > 4)
                return count;
        if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-               printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
+               printk("%s: wait_for_debi_done #2 failed\n", __func__);
                return 0;
        }
 
@@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
                        break;
                if (err) {
                        printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
-                               __FUNCTION__, stat & flags);
+                               __func__, stat & flags);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
                        av7110->arm_errors++;
                        return -ETIMEDOUT;
                }
@@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
                        if (stat & flags[0]) {
                                printk(KERN_ERR "%s: %s QUEUE overflow\n",
-                                       __FUNCTION__, type);
+                                       __func__, type);
                                return -1;
                        }
                        if ((stat & flags[1]) == 0)
                                break;
                        if (err) {
                                printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
-                                       __FUNCTION__, type);
+                                       __func__, type);
                                return -ETIMEDOUT;
                        }
                        msleep(1);
@@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        break;
                if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
-                              __FUNCTION__, (buf[0] >> 8) & 0xff);
+                              __func__, (buf[0] >> 8) & 0xff);
                        return -ETIMEDOUT;
                }
                msleep(1);
@@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 
        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
        if (stat & GPMQOver) {
-               printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
+               printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
                return -ENOSPC;
        }
        else if (stat & OSDQOver) {
-               printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
+               printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
                return -ENOSPC;
        }
 #endif
@@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
        mutex_unlock(&av7110->dcomlock);
        if (ret && ret!=-ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
-                      __FUNCTION__, ret);
+                      __func__, ret);
        return ret;
 }
 
@@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
+                       printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
                        break;
                if (err) {
-                       printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+                       printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
 #ifdef COM_DEBUG
        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
        if (stat & GPMQOver) {
-               printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
+               printk(KERN_ERR "%s: GPMQOver\n", __func__);
                mutex_unlock(&av7110->dcomlock);
                return -1;
        }
        else if (stat & OSDQOver) {
-               printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
+               printk(KERN_ERR "%s: OSDQOver\n", __func__);
                mutex_unlock(&av7110->dcomlock);
                return -1;
        }
@@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110)
                        break;
                if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
                        break;
                if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
@@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
                        break;
                if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
-                              __FUNCTION__);
+                              __func__);
                        mutex_unlock(&av7110->dcomlock);
                        return -ETIMEDOUT;
                }
index a283e1de83facf6edc5ebae02b6ae232d477b885..23a1c6380d3f22964ef98ead022c3b3442901536 100644 (file)
@@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm)
                break;
 
        default:
-               printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol);
+               printk("%s invalid protocol %x\n", __func__, ir->protocol);
                return;
        }
 
@@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm)
        keycode = ir->key_map[data];
 
        dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
-               __FUNCTION__, ircom, addr, data, keycode);
+               __func__, ircom, addr, data, keycode);
 
        /* check device address */
        if (!(ir->device_mask & (1 << addr)))
@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
 
        if (!keycode) {
                printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
-                       __FUNCTION__, ircom, addr, data);
+                       __func__, ircom, addr, data);
                return;
        }
 
index e2f066fb796727c1f0f7bf1c8196a562d25c1839..b4a0cc5dc935ffec2c9310385c7816d1e24f40a4 100644 (file)
@@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file)
        struct saa7146_dev *dev = fh->dev;
        struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        av7110->wssMode = 0;
        av7110->wssData = 0;
        if (FW_VERSION(av7110->arm_app) < 0x2623)
@@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
        struct v4l2_sliced_vbi_data d;
        int rc;
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
                return -EINVAL;
        if (copy_from_user(&d, data, count))
index 2d64d557b9770f3d13b8fd3ccf8add46ac7c66aa..b30a5288e484fb837e2985c41180be506de01a8b 100644 (file)
@@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
        udelay(1);
 
        result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-       if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+       if (result == -ETIMEDOUT) {
                ciintf_slot_shutdown(ca, slot);
                printk(KERN_INFO "budget-av: cam ejected 3\n");
                return -ETIMEDOUT;
@@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_0,
+       .lock_output = STV0299_LOCKOUTPUT_0,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -869,7 +869,7 @@ static struct stv0299_config philips_sd1878_config = {
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
@@ -941,6 +941,12 @@ static void frontend_init(struct budget_av *budget_av)
        switch (saa->pci->subsystem_device) {
 
        case SUBID_DVBS_KNC1:
+               /*
+                * maybe that setting is needed for other dvb-s cards as well,
+                * but so far it has been only confirmed for this type
+                */
+               budget_av->reinitialise_demod = 1;
+               /* fall through */
        case SUBID_DVBS_KNC1_PLUS:
        case SUBID_DVBS_EASYWATCH_1:
                if (saa->pci->subsystem_vendor == 0x1894) {
index 509349211d4fc40594fb99a27980eeed2ae66e31..6530323d540617259db6c46f4bc7150d3b9858d1 100644 (file)
@@ -86,7 +86,7 @@ static int rc5_device = -1;
 module_param(rc5_device, int, 0644);
 MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
 
-static int ir_debug = 0;
+static int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
 
@@ -728,7 +728,7 @@ static struct stv0299_config philips_su1278_tt_config = {
        .mclk = 64000000UL,
        .invert = 0,
        .skip_reinit = 1,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 50,
        .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
@@ -1121,7 +1121,7 @@ static void frontend_init(struct budget_ci *budget_ci)
 
                        budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
                        if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                                budget_ci->budget.dvb_frontend = NULL;
                        }
index 0252081f013c56d86d3217d37c5a586f67c7da6e..18cac4b12ab28f73fb97a25f219788438b703bee 100644 (file)
@@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
 MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
 MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /****************************************************************************
  * TT budget / WinTV Nova
  ****************************************************************************/
@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
 
        if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
                printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
-                       budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+                       budget->dev->name, __func__, budget->buffer_warnings, count);
                budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
                budget->buffer_warnings = 0;
        }
@@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
                budget->buffer_width, budget->buffer_height);
        printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 
-       if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+       ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
+                                  owner, &budget->dev->pci->dev, adapter_nr);
+       if (ret < 0)
                return ret;
-       }
 
        /* set dd1 stream a & b */
        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
index 14b00f57b5de80ce18d57211dd5c6b9e8c6179da..2293d80c6e5131fcad7feed54d7823581571ac65 100644 (file)
@@ -45,6 +45,7 @@
 #include "tda826x.h"
 #include "lnbp21.h"
 #include "bsru6.h"
+#include "bsbe1.h"
 
 static int diseqc_method;
 module_param(diseqc_method, int, 0444);
@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
 
 static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
-       struct budget* budget = (struct budget*) fe->dvb->priv;
+       struct budget *budget = fe->dvb->priv;
+       u8 *tuner_addr = fe->tuner_priv;
        u32 div;
        u8 cfg, cpump, band_select;
        u8 data[4];
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+       struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
+
+       if (tuner_addr)
+               msg.addr = *tuner_addr;
+       else
+               msg.addr = 0x61;
 
        div = (36125000 + params->frequency) / 166666;
 
@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
        .demod_address = 0x55,
 };
 
+static struct l64781_config grundig_29504_401_config_activy = {
+       .demod_address = 0x54,
+};
+
+static u8 tuner_address_grundig_29504_401_activy = 0x60;
+
 static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -346,14 +359,48 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
 static struct s5h1420_config s5h1420_config = {
        .demod_address = 0x53,
        .invert = 1,
+       .cdclk_polarity = 1,
 };
 
 static struct tda10086_config tda10086_config = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 1,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
+static struct stv0299_config alps_bsru6_config_activy = {
+       .demod_address = 0x68,
+       .inittab = alps_bsru6_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .op0_off = 1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = alps_bsru6_set_symbol_rate,
+};
+
+static struct stv0299_config alps_bsbe1_config_activy = {
+       .demod_address = 0x68,
+       .inittab = alps_bsbe1_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .op0_off = 1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = alps_bsbe1_set_symbol_rate,
+};
+
+
+static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
+{
+       u8 val;
+       struct i2c_msg msg[] = {
+               { .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
+               { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+       };
+
+       return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
+}
+
 static u8 read_pwm(struct budget* budget)
 {
        u8 b = 0xff;
@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
 
 static void frontend_init(struct budget *budget)
 {
+       (void)alps_bsbe1_config; /* avoid warning */
+
        switch(budget->dev->pci->subsystem_device) {
        case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
        case 0x1013:
@@ -414,15 +463,43 @@ static void frontend_init(struct budget *budget)
                }
                break;
 
-       case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
-               budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
-               if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-                       budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
-                       budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+       case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
+       {
+               int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
+
+               if (subtype < 0)
+                       break;
+               /* fixme: find a better way to identify the card */
+               if (subtype < 0x36) {
+                       /* assume ALPS BSRU6 */
+                       budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
+                       if (budget->dvb_frontend) {
+                               printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
+                               budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                               budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                               budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                               budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+                               break;
+                       }
+               } else {
+                       /* assume ALPS BSBE1 */
+                       /* reset tuner */
+                       saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
+                       msleep(50);
+                       saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
+                       msleep(250);
+                       budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
+                       if (budget->dvb_frontend) {
+                               printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
+                               budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+                               budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                               budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                               budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+                               break;
+                       }
                }
                break;
+       }
 
        case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
                budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
@@ -433,12 +510,20 @@ static void frontend_init(struct budget *budget)
                }
                break;
 
+       case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
+               budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+               }
+               break;
+
        case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
                budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
                        if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                goto error_out;
                        }
                        break;
@@ -454,9 +539,9 @@ static void frontend_init(struct budget *budget)
                budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
-                               printk("%s: No tda826x found!\n", __FUNCTION__);
+                               printk("%s: No tda826x found!\n", __func__);
                        if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               printk("%s: No LNBP21 found!\n", __func__);
                                goto error_out;
                        }
                        break;
@@ -537,6 +622,7 @@ MAKE_BUDGET_INFO(satel,     "SATELCO Multimedia PCI",       BUDGET_TT_HW_DISEQC);
 MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsact,         "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
@@ -547,6 +633,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
+       MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
        {
                .vendor    = 0,
        }
index d764ffa728b0c48bfc1ba5864d529d72803b1dfe..dd450b739bff9bb21d56c2bc8d2dae3d6c4dab54 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef __BUDGET_DVB__
 #define __BUDGET_DVB__
 
@@ -21,7 +22,7 @@ extern int budget_debug;
 #endif
 
 #define dprintk(level,args...) \
-           do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
+           do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
 
 struct budget_info {
        char *name;
index 1f31e91195b0c6817718d5ca4f6658247064416f..7dd54b3026a251c9eb4ba7fbd69dc71fbdd8edb1 100644 (file)
@@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
                { .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
        };
 
-       /* dprintk("%s\n", __FUNCTION__); */
+       /* dprintk("%s\n", __func__); */
 
        ret = i2c_transfer(adapter, msg, 2);
 
index 7902ae1d9a181c80e205eac147fdb92d3f704ee4..732ce4de512eaa392e12151150adb7c7940a19cf 100644 (file)
 */
 
 static int debug;
-
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
 
 #define ISO_BUF_COUNT      4
@@ -153,12 +154,12 @@ static int ttusb_cmd(struct ttusb *ttusb,
                           (u8 *) data, len, &actual_len, 1000);
        if (err != 0) {
                dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
                mutex_unlock(&ttusb->semusb);
                return err;
        }
        if (actual_len != len) {
-               dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
+               dprintk("%s: only wrote %d of %d bytes\n", __func__,
                        actual_len, len);
                mutex_unlock(&ttusb->semusb);
                return -1;
@@ -168,7 +169,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
                           ttusb->last_result, 32, &actual_len, 1000);
 
        if (err != 0) {
-               printk("%s: failed, receive error %d\n", __FUNCTION__,
+               printk("%s: failed, receive error %d\n", __func__,
                       err);
                mutex_unlock(&ttusb->semusb);
                return err;
@@ -229,7 +230,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
                if (err || b[0] != 0x55 || b[1] != id) {
                        dprintk
                            ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
-                            __FUNCTION__, err, id);
+                            __func__, err, id);
                        return -EREMOTEIO;
                }
 
@@ -273,7 +274,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
                                    snd_buf, snd_len, rcv_buf, rcv_len);
 
                if (err < rcv_len) {
-                       dprintk("%s: i == %i\n", __FUNCTION__, i);
+                       dprintk("%s: i == %i\n", __func__, i);
                        break;
                }
 
@@ -327,7 +328,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
       done:
        if (err) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -427,7 +428,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
        if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
                return err;
 
-       dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
+       dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
                get_version[4], get_version[5], get_version[6],
                get_version[7], get_version[8]);
 
@@ -437,7 +438,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
            memcmp(get_version + 4, "V 2.2", 5)) {
                printk
                    ("%s: unknown STC version %c%c%c%c%c, please report!\n",
-                    __FUNCTION__, get_version[4], get_version[5],
+                    __func__, get_version[4], get_version[5],
                     get_version[6], get_version[7], get_version[8]);
        }
 
@@ -453,7 +454,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
            ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
        if (err)
                return err;
-       printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
+       printk("%s: dsp-version: %c%c%c\n", __func__,
               get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
        return 0;
 }
@@ -476,7 +477,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
        /* Diseqc */
        if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -494,7 +495,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb)
        /* SetLNB */
        if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 
        return err;
@@ -528,7 +529,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
        err = ttusb_cmd(ttusb, b, sizeof(b), 0);
        if (err) {
                dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        }
 }
 #endif
@@ -542,7 +543,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
                                  const u8 * data, int len);
 #endif
 
-static int numpkt = 0, numts, numstuff, numsec, numinvalid;
+static int numpkt, numts, numstuff, numsec, numinvalid;
 static unsigned long lastj;
 
 static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
@@ -554,7 +555,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
                csum ^= le16_to_cpup((u16 *) (muxpack + i));
        if (csum) {
                printk("%s: muxpack with incorrect checksum, ignoring\n",
-                      __FUNCTION__);
+                      __func__);
                numinvalid++;
                return;
        }
@@ -563,7 +564,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
        cc &= 0x7FFF;
        if ((cc != ttusb->cc) && (ttusb->cc != -1))
                printk("%s: cc discontinuity (%d frames missing)\n",
-                      __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
+                      __func__, (cc - ttusb->cc) & 0x7FFF);
        ttusb->cc = (cc + 1) & 0x7FFF;
        if (muxpack[0] & 0x80) {
 #ifdef TTUSB_HWSECTIONS
@@ -613,7 +614,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
        int maxwork = 1024;
        while (len) {
                if (!(maxwork--)) {
-                       printk("%s: too much work\n", __FUNCTION__);
+                       printk("%s: too much work\n", __func__);
                        break;
                }
 
@@ -632,7 +633,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
 #else
                                if (ttusb->insync) {
                                        printk("%s: lost sync.\n",
-                                              __FUNCTION__);
+                                              __func__);
                                        ttusb->insync = 0;
                                }
 #endif
@@ -691,7 +692,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
                                        else {
                                                dprintk
                                                    ("%s: invalid state: first byte is %x\n",
-                                                    __FUNCTION__,
+                                                    __func__,
                                                     ttusb->muxpack[0]);
                                                ttusb->mux_state = 0;
                                        }
@@ -740,7 +741,7 @@ static void ttusb_iso_irq(struct urb *urb)
 
 #if 0
        printk("%s: status %d, errcount == %d, length == %i\n",
-              __FUNCTION__,
+              __func__,
               urb->status, urb->error_count, urb->actual_length);
 #endif
 
@@ -833,7 +834,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
        int i, j, err, buffer_offset = 0;
 
        if (ttusb->iso_streaming) {
-               printk("%s: iso xfer already running!\n", __FUNCTION__);
+               printk("%s: iso xfer already running!\n", __func__);
                return 0;
        }
 
@@ -869,7 +870,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
                        ttusb_stop_iso_xfer(ttusb);
                        printk
                            ("%s: failed urb submission (%i: err = %i)!\n",
-                            __FUNCTION__, i, err);
+                            __func__, i, err);
                        return err;
                }
        }
@@ -1005,7 +1006,7 @@ static int stc_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations stc_fops = {
+static const struct file_operations stc_fops = {
        .owner = THIS_MODULE,
        .read = stc_read,
        .open = stc_open,
@@ -1313,7 +1314,7 @@ static struct stv0299_config alps_stv0299_config = {
        .mclk = 88000000UL,
        .invert = 1,
        .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
+       .lock_output = STV0299_LOCKOUTPUT_1,
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_stv0299_set_symbol_rate,
@@ -1643,7 +1644,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct ttusb *ttusb;
        int result;
 
-       dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
+       dprintk("%s: TTUSB DVB connected\n", __func__);
 
        udev = interface_to_usbdev(intf);
 
@@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        mutex_unlock(&ttusb->semi2c);
 
-       if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
+       result = dvb_register_adapter(&ttusb->adapter,
+                                     "Technotrend/Hauppauge Nova-USB",
+                                     THIS_MODULE, &udev->dev, adapter_nr);
+       if (result < 0) {
                ttusb_free_iso_urbs(ttusb);
                kfree(ttusb);
                return result;
@@ -1773,7 +1777,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
 
        kfree(ttusb);
 
-       dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
+       dprintk("%s: TTUSB DVB disconnected\n", __func__);
 }
 
 static struct usb_device_id ttusb_table[] = {
index 1ec981d98b91bf60da958e0530dccca725b68474..42eee04daa5da4407c4d383982aeffbf51c1f15c 100644 (file)
@@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
 module_param(enable_rc, int, 0644);
 MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk        if (debug) printk
 
 #define DRIVER_NAME            "TechnoTrend/Hauppauge DEC USB"
@@ -217,11 +219,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                case -ETIME:
                        /* this urb is dead, cleanup */
                        dprintk("%s:urb shutting down with status: %d\n",
-                                       __FUNCTION__, urb->status);
+                                       __func__, urb->status);
                        return;
                default:
                        dprintk("%s:nonzero status received: %d\n",
-                                       __FUNCTION__,urb->status);
+                                       __func__,urb->status);
                        goto exit;
        }
 
@@ -235,7 +237,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                 * keyrepeat signal is recieved for lets say 200ms.
                 * this should/could be added later ...
                 * for now lets report each signal as a key down and up*/
-               dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
+               dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
                input_sync(dec->rc_input_dev);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
@@ -245,7 +247,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
 exit:  retval = usb_submit_urb(urb, GFP_ATOMIC);
        if(retval)
                printk("%s - usb_commit_urb failed with result: %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 static u16 crc16(u16 crc, const u8 *buf, size_t len)
@@ -268,7 +270,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
        int result, actual_len, i;
        u8 *b;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
        if (!b)
@@ -276,7 +278,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
                kfree(b);
-               printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
+               printk("%s: Failed to lock usb mutex.\n", __func__);
                return result;
        }
 
@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
                memcpy(&b[4], params, param_length);
 
        if (debug) {
-               printk("%s: command: ", __FUNCTION__);
+               printk("%s: command: ", __func__);
                for (i = 0; i < param_length + 4; i++)
                        printk("0x%02X ", b[i]);
                printk("\n");
@@ -300,7 +302,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if (result) {
                printk("%s: command bulk message failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
                mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
@@ -311,13 +313,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
 
        if (result) {
                printk("%s: result bulk message failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
                mutex_unlock(&dec->usb_mutex);
                kfree(b);
                return result;
        } else {
                if (debug) {
-                       printk("%s: result: ", __FUNCTION__);
+                       printk("%s: result: ", __func__);
                        for (i = 0; i < actual_len; i++)
                                printk("0x%02X ", b[i]);
                        printk("\n");
@@ -343,7 +345,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
        int result;
        unsigned int tmp;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
        if (result)
@@ -400,7 +402,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
        u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
        u16 video = htons(dec->pid[DMX_PES_VIDEO]);
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        memcpy(&b[0], &pcr, 2);
        memcpy(&b[2], &audio, 2);
@@ -419,12 +421,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
 static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
 {
        if (length < 8) {
-               printk("%s: packet too short - discarding\n", __FUNCTION__);
+               printk("%s: packet too short - discarding\n", __func__);
                return;
        }
 
        if (length > 8 + MAX_PVA_LENGTH) {
-               printk("%s: packet too long - discarding\n", __FUNCTION__);
+               printk("%s: packet too long - discarding\n", __func__);
                return;
        }
 
@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
                break;
 
        default:
-               printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
+               printk("%s: unknown PVA type: %02x.\n", __func__,
                       pva[2]);
                break;
        }
@@ -546,7 +548,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
        u16 packet_id;
 
        if (dec->packet_length % 2) {
-               printk("%s: odd sized packet - discarding\n", __FUNCTION__);
+               printk("%s: odd sized packet - discarding\n", __func__);
                return;
        }
 
@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
                csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
 
        if (csum) {
-               printk("%s: checksum failed - discarding\n", __FUNCTION__);
+               printk("%s: checksum failed - discarding\n", __func__);
                return;
        }
 
@@ -563,7 +565,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
 
        if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
                printk("%s: warning: lost packets between %u and %u\n",
-                      __FUNCTION__, dec->next_packet_id - 1, packet_id);
+                      __func__, dec->next_packet_id - 1, packet_id);
        }
 
        if (packet_id == 0xffff)
@@ -652,7 +654,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
                                        dec->packet_state = 7;
                                } else {
                                        printk("%s: unknown packet type: "
-                                              "%02x%02x\n", __FUNCTION__,
+                                              "%02x%02x\n", __func__,
                                               dec->packet[0], dec->packet[1]);
                                        dec->packet_state = 0;
                                }
@@ -724,7 +726,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
 
                default:
                        printk("%s: illegal packet state encountered.\n",
-                              __FUNCTION__);
+                              __func__);
                        dec->packet_state = 0;
                }
        }
@@ -792,7 +794,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
        } else {
                 /* -ENOENT is expected when unlinking urbs */
                if (urb->status != -ENOENT)
-                       dprintk("%s: urb error: %d\n", __FUNCTION__,
+                       dprintk("%s: urb error: %d\n", __func__,
                                urb->status);
        }
 
@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
 {
        int i, j, buffer_offset = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        for (i = 0; i < ISO_BUF_COUNT; i++) {
                int frame_offset = 0;
@@ -834,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (mutex_lock_interruptible(&dec->iso_mutex))
                return;
@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
 {
        int i, result;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (mutex_lock_interruptible(&dec->iso_mutex))
                return -EAGAIN;
@@ -905,7 +907,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
                        if ((result = usb_submit_urb(dec->iso_urb[i],
                                                     GFP_ATOMIC))) {
                                printk("%s: failed urb submission %d: "
-                                      "error %d\n", __FUNCTION__, i, result);
+                                      "error %d\n", __func__, i, result);
 
                                while (i) {
                                        usb_kill_urb(dec->iso_urb[i - 1]);
@@ -932,7 +934,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
        u8 b0[] = { 0x05 };
        int result = 0;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dprintk("  ts_type:");
 
@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
        unsigned long flags;
        u8 x = 1;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        pid = htons(dvbdmxfeed->pid);
        memcpy(&b0[0], &pid, 2);
@@ -1052,7 +1054,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (!dvbdmx->dmx.frontend)
                return -EINVAL;
@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
 
 static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        switch (dvbdmxfeed->type) {
        case DMX_TYPE_TS:
@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        for (i = 0; i < ISO_BUF_COUNT; i++)
                usb_free_urb(dec->iso_urb[i]);
@@ -1147,7 +1149,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->iso_buffer = pci_alloc_consistent(NULL,
                                               ISO_FRAME_SIZE *
@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
 
        dec->rc_input_dev = input_dev;
        if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
-               printk("%s: usb_submit_urb failed\n",__FUNCTION__);
+               printk("%s: usb_submit_urb failed\n",__func__);
        /* enable irq pipe */
        ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
 
@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
 
 static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->v_pes[0] = 0x00;
        dec->v_pes[1] = 0x00;
@@ -1233,7 +1235,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
 
 static int ttusb_dec_init_usb(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        mutex_init(&dec->usb_mutex);
        mutex_init(&dec->iso_mutex);
@@ -1281,11 +1283,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        u32 crc32_csum, crc32_check, tmp;
        const struct firmware *fw_entry = NULL;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
                printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
-                      __FUNCTION__, dec->firmware_name);
+                      __func__, dec->firmware_name);
                return 1;
        }
 
@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        if (firmware_size < 60) {
                printk("%s: firmware size too small for DSP code (%zu < 60).\n",
-                       __FUNCTION__, firmware_size);
+                       __func__, firmware_size);
                release_firmware(fw_entry);
                return -1;
        }
@@ -1308,7 +1310,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        if (crc32_csum != crc32_check) {
                printk("%s: crc32 check of DSP code failed (calculated "
                       "0x%08x != 0x%08x in file), file invalid.\n",
-                       __FUNCTION__, crc32_csum, crc32_check);
+                       __func__, crc32_csum, crc32_check);
                release_firmware(fw_entry);
                return -1;
        }
@@ -1376,7 +1378,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
        int result;
        unsigned int mode, model, version;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
 
@@ -1415,7 +1417,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
                        default:
                                printk(KERN_ERR "%s: unknown model returned "
                                       "by firmware (%08x) - please report\n",
-                                      __FUNCTION__, model);
+                                      __func__, model);
                                return -1;
                                break;
                        }
@@ -1434,12 +1436,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 {
        int result;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if ((result = dvb_register_adapter(&dec->adapter,
-                                          dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
+                                          dec->model_name, THIS_MODULE,
+                                          &dec->udev->dev,
+                                          adapter_nr)) < 0) {
                printk("%s: dvb_register_adapter failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
 
                return result;
        }
@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
        dec->demux.write_to_decoder = NULL;
 
        if ((result = dvb_dmx_init(&dec->demux)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dvb_unregister_adapter(&dec->adapter);
@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
                printk("%s: dvb_dmxdev_init failed: error %d\n",
-                      __FUNCTION__, result);
+                      __func__, result);
 
                dvb_dmx_release(&dec->demux);
                dvb_unregister_adapter(&dec->adapter);
@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
                                                  &dec->frontend)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dvb_dmxdev_release(&dec->dmxdev);
@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
        if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
                                                      &dec->frontend)) < 0) {
-               printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+               printk("%s: dvb_dmx_init failed: error %d\n", __func__,
                       result);
 
                dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
 
 static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
 {
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dvb_net_release(&dec->dvb_net);
        dec->demux.dmx.close(&dec->demux.dmx);
@@ -1528,7 +1532,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
 static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
 {
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
        /* we have to check whether the irq URB is already submitted.
          * As the irq is submitted after the interface is changed,
          * this is the best method i figured out.
@@ -1552,7 +1556,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
 {
        int i;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        dec->iso_stream_count = 0;
 
@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
        struct usb_device *udev;
        struct ttusb_dec *dec;
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        udev = interface_to_usbdev(intf);
 
        if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
-               printk("%s: couldn't allocate memory.\n", __FUNCTION__);
+               printk("%s: couldn't allocate memory.\n", __func__);
                return -ENOMEM;
        }
 
@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
 
-       dprintk("%s\n", __FUNCTION__);
+       dprintk("%s\n", __func__);
 
        if (dec->active) {
                ttusb_dec_exit_tasklet(dec);
@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
        int result;
 
        if ((result = usb_register(&ttusb_dec_driver)) < 0) {
-               printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
+               printk("%s: initialisation failed: error %d.\n", __func__,
                       result);
                return result;
        }
index a6fb1d6a7b5dd168394933b9abb609ae3c7f6c19..eb5eaeccd7c4db2dc16e8ee948f08802d7851cb3 100644 (file)
@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
                return ret;
 
        if(len != 4) {
-               printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+               printk(KERN_ERR "%s: unexpected reply\n", __func__);
                return -EIO;
        }
 
@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
                        break;
                default:
                        pr_info("%s: returned unknown value: %d\n",
-                               __FUNCTION__, result[3]);
+                               __func__, result[3]);
                        return -EIO;
        }
 
index 36c0e365150241ebe1561c7aaa09d738cddbcf15..4e3f83e4e48f34f4f2878df5823c00f3f0729bc7 100644 (file)
@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
        .open           = usb_dsbr100_open,
        .release        = usb_dsbr100_close,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 3ae56fef8c92f58ce4d2b2123606b795e0adf503..09fe6f1cdf14b124d8b10fcc64e91bc91625649e 100644 (file)
@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = pcm20_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index aed11477378bd5bf018a9d7a4eec1e9c960ca86e..06dfed9ef4c7194d043999d23ed7eda35e9025c4 100644 (file)
@@ -19,7 +19,7 @@
 #include "miropcm20-rds-core.h"
 
 static char * text_buffer;
-static int rds_users = 0;
+static int rds_users;
 
 
 static int rds_f_open(struct inode *in, struct file *fi)
index c69bde39a2336c8ae623001bc7465139abc4f693..1ec18ed1a73365dbfad685238648f63faeba4177 100644 (file)
@@ -382,7 +382,9 @@ static const struct file_operations rtrack_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 9b1f7a99dac0ac4c6b71dcfb836ef5d4fc18bf68..46cdb549eac736eb1321777e9616e2f7fe5070d8 100644 (file)
@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 57b9e3adc8f0249c831bf93dcbf49658d859d608..b14db53ea456514153ee49ae0a61759c3d522847 100644 (file)
@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 
 static int io=-1;              /* default to isapnp activation */
 static int radio_nr = -1;
-static int users=0;
-static int curtuner=0;
-static int tunestat=0;
-static int sigstrength=0;
+static int users;
+static int curtuner;
+static int tunestat;
+static int sigstrength;
 static wait_queue_head_t read_queue;
 static struct timer_list readtimer;
-static __u8 rdsin=0,rdsout=0,rdsstat=0;
+static __u8 rdsin, rdsout, rdsstat;
 static unsigned char rdsbuf[RDS_BUFFER];
 static spinlock_t cadet_io_lock;
 
@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
        .read           = cadet_read,
        .ioctl          = video_ioctl2,
        .poll           = cadet_poll,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 99a3231313332b5736e43dd218352a9a15454115..de49be971480fd8ec1b569904f8d329fd3ee821f 100644 (file)
@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 246422b49267ca3bf1a6bd3efa425cd778de2c42..81f6aeb1cd1154d62e707d41d620381fa100c25c 100644 (file)
@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek
 };
 
index bc51f4d23a5a176abbc61007d7d8dbfdec21e5e9..bddd3c409aa95a84112b1930ea0844ab060b4150 100644 (file)
@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 8e184cfc1c94aa897665f73e6a21fec40c26d973..0133ecf3e040b0905f157581283c384f6ec7b876 100644 (file)
@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 82aedfc95d4f3883b0e487402a53d21631baf494..070802103dc34d52176b87fa78c43511f2ce3798 100644 (file)
@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 53e1148573778de36291239684bd1d9b0093fe2a..66e052fd3909aa3531ce5e7b1e22bfe91f865537 100644 (file)
@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index ebc5fbbc38bb3534b408cccd0785e2a5e2ea80fd..b0ccf7cb5952a8c0edda2ef0588a0800fe1a6682 100644 (file)
@@ -29,6 +29,8 @@ static struct mutex lock;
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
 
+#define AUD_VOL_INDEX 1
+
 static struct v4l2_queryctrl radio_qctrl[] = {
        {
                .id            = V4L2_CID_AUDIO_MUTE,
@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = {
                .maximum       = 1,
                .default_value = 1,
                .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
+       },
+       [AUD_VOL_INDEX] = {
                .id            = V4L2_CID_AUDIO_VOLUME,
                .name          = "Volume",
                .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 1<<12,
-               .default_value = 0xff,
+               .maximum       = 15,
+               .step          = 1,
+               .default_value = 0,
                .type          = V4L2_CTRL_TYPE_INTEGER,
        }
 };
@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 struct fmr2_device
 {
        int port;
-       int curvol; /* 0-65535, if not volume 0 or 65535 */
+       int curvol; /* 0-15 */
        int mute;
        int stereo; /* card is producing stereo audio */
        unsigned long curfreq; /* freq in kHz */
@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev)
 /* !!! not tested, in my card this does't work !!! */
 static int fmr2_setvolume(struct fmr2_device *dev)
 {
-       int i,a,n, port = dev->port;
+       int vol[16] = { 0x021, 0x084, 0x090, 0x104,
+                       0x110, 0x204, 0x210, 0x402,
+                       0x404, 0x408, 0x410, 0x801,
+                       0x802, 0x804, 0x808, 0x810 };
+       int i, a, port = dev->port;
+       int n = vol[dev->curvol & 0x0f];
 
-       if (dev->card_type != 11) return 1;
+       if (dev->card_type != 11)
+               return 1;
 
-       switch( (dev->curvol+(1<<11)) >> 12 )
-       {
-       case 0: case 1: n = 0x21; break;
-       case 2: n = 0x84; break;
-       case 3: n = 0x90; break;
-       case 4: n = 0x104; break;
-       case 5: n = 0x110; break;
-       case 6: n = 0x204; break;
-       case 7: n = 0x210; break;
-       case 8: n = 0x402; break;
-       case 9: n = 0x404; break;
-       default:
-       case 10: n = 0x408; break;
-       case 11: n = 0x410; break;
-       case 12: n = 0x801; break;
-       case 13: n = 0x802; break;
-       case 14: n = 0x804; break;
-       case 15: n = 0x808; break;
-       case 16: n = 0x810; break;
-       }
-       for(i=12;--i>=0;)
-       {
+       for (i = 12; --i >= 0; ) {
                a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
-               outb(a|4, port);
-               wait(4,port);
-               outb(a|0x24, port);
-               wait(4,port);
-               outb(a|4, port);
-               wait(4,port);
+               outb(a | 4, port);
+               wait(4, port);
+               outb(a | 0x24, port);
+               wait(4, port);
+               outb(a | 4, port);
+               wait(4, port);
        }
-       for(i=6;--i>=0;)
-       {
+       for (i = 6; --i >= 0; ) {
                a = ((0x18 >> i) & 1) << 6;
-               outb(a|4, port);
+               outb(a | 4, port);
                wait(4,port);
-               outb(a|0x24, port);
+               outb(a | 0x24, port);
                wait(4,port);
                outb(a|4, port);
                wait(4,port);
        }
-       wait(4,port);
+       wait(4, port);
        outb(0x14, port);
 
        return 0;
@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv,
                                        struct v4l2_queryctrl *qc)
 {
        int i;
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
 
        for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-               if ((fmr2->card_type != 11)
-                               && V4L2_CID_AUDIO_VOLUME)
-                       radio_qctrl[i].step = 65535;
                if (qc->id && qc->id == radio_qctrl[i].id) {
-                       memcpy(qc, &(radio_qctrl[i]),
-                                               sizeof(*qc));
+                       memcpy(qc, &radio_qctrl[i], sizeof(*qc));
                        return 0;
                }
        }
@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                fmr2->mute = ctrl->value;
-               if (fmr2->card_type != 11) {
-                       if (!fmr2->mute)
-                               fmr2->curvol = 65535;
-                       else
-                               fmr2->curvol = 0;
-               }
                break;
        case V4L2_CID_AUDIO_VOLUME:
-               fmr2->curvol = ctrl->value;
-               if (fmr2->card_type != 11) {
-                       if (fmr2->curvol) {
-                               fmr2->curvol = 65535;
-                               fmr2->mute = 0;
-                       } else {
-                               fmr2->curvol = 0;
-                               fmr2->mute = 1;
-                       }
-               }
+               if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
+                       fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
+               else
+                       fmr2->curvol = ctrl->value;
+
                break;
        default:
                return -EINVAL;
@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        mutex_lock(&lock);
        if (fmr2->curvol && !fmr2->mute) {
                fmr2_setvolume(fmr2);
+               /* Set frequency and unmute card */
                fmr2_setfreq(fmr2);
        } else
                fmr2_mute(fmr2->port);
@@ -433,7 +404,9 @@ static const struct file_operations fmr2_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
@@ -487,6 +460,11 @@ static int __init fmr2_init(void)
        fmr2_product_info(&fmr2_unit);
        mutex_unlock(&lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
+
+       /* Only card_type == 11 implements volume */
+       if (fmr2_unit.card_type != 11)
+               radio_qctrl[AUD_VOL_INDEX].maximum = 1;
+
        return 0;
 }
 
index 649f14d2c01340e4bdea2bee6d4b1910ee39e496..77354ca6e8e928005cfcf631ed97d698bfd9b1ab 100644 (file)
@@ -85,6 +85,7 @@
  *             Oliver Neukum <oliver@neukum.org>
  *             Version 1.0.7
  *             - usb autosuspend support
+ *             - unplugging fixed
  *
  * ToDo:
  * - add seeking support
 /* driver definitions */
 #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
 #define DRIVER_NAME "radio-si470x"
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.6"
+#define DRIVER_VERSION "1.0.7"
 
 
 /* kernel includes */
@@ -424,6 +425,7 @@ struct si470x_device {
 
        /* driver management */
        unsigned int users;
+       unsigned char disconnected;
 
        /* Silabs internal registers (0..15) */
        unsigned short registers[RADIO_REGISTER_NUM];
@@ -439,6 +441,12 @@ struct si470x_device {
 };
 
 
+/*
+ * Lock to prevent kfree of data before all users have releases the device.
+ */
+static DEFINE_MUTEX(open_close_lock);
+
+
 /*
  * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
  * 62.5 kHz otherwise.
@@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
                usb_rcvintpipe(radio->usbdev, 1),
                (void *) &buf, sizeof(buf), &size, usb_timeout);
        if (size != sizeof(buf))
-               printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
+              printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
                        "return size differs: %d != %zu\n", size, sizeof(buf));
        if (retval < 0)
                printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work)
        struct si470x_device *radio = container_of(work, struct si470x_device,
                work.work);
 
+       if (radio->disconnected)
+              return;
        if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
                return;
 
@@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
 static int si470x_fops_release(struct inode *inode, struct file *file)
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
-       int retval;
+       int retval = 0;
 
        if (!radio)
                return -ENODEV;
 
+       mutex_lock(&open_close_lock);
        radio->users--;
        if (radio->users == 0) {
+              if (radio->disconnected) {
+                      video_unregister_device(radio->videodev);
+                      kfree(radio->buffer);
+                      kfree(radio);
+                      goto done;
+              }
+
                /* stop rds reception */
                cancel_delayed_work_sync(&radio->work);
 
@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
 
                retval = si470x_stop(radio);
                usb_autopm_put_interface(radio->intf);
-               return retval;
        }
 
-       return 0;
+done:
+       mutex_unlock(&open_close_lock);
+       return retval;
 }
 
 
@@ -1032,7 +1051,9 @@ static const struct file_operations si470x_fops = {
        .read           = si470x_fops_read,
        .poll           = si470x_fops_poll,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .open           = si470x_fops_open,
        .release        = si470x_fops_release,
 };
@@ -1157,6 +1178,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
 
+       if (radio->disconnected)
+              return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_VOLUME:
                ctrl->value = radio->registers[SYSCONFIG2] &
@@ -1181,6 +1205,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
+
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_VOLUME:
                radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
@@ -1243,6 +1270,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (tuner->index > 0)
                return -EINVAL;
 
@@ -1299,6 +1328,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (tuner->index > 0)
                return -EINVAL;
 
@@ -1324,6 +1355,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
 {
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
 
+       if (radio->disconnected)
+              return -EIO;
+
        freq->type = V4L2_TUNER_RADIO;
        freq->frequency = si470x_get_freq(radio);
 
@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
        struct si470x_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
 
+       if (radio->disconnected)
+              return -EIO;
        if (freq->type != V4L2_TUNER_RADIO)
                return -EINVAL;
 
@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
 {
        struct si470x_device *radio = usb_get_intfdata(intf);
 
+       mutex_lock(&open_close_lock);
+       radio->disconnected = 1;
        cancel_delayed_work_sync(&radio->work);
        usb_set_intfdata(intf, NULL);
-       video_unregister_device(radio->videodev);
-       kfree(radio->buffer);
-       kfree(radio);
+       if (radio->users == 0) {
+              video_unregister_device(radio->videodev);
+              kfree(radio->buffer);
+              kfree(radio);
+       }
+       mutex_unlock(&open_close_lock);
 }
 
 
index 535ffe8c81028508ac773c05510a8f895c35678d..acc32080e9bdefef40bc84d0e2e0bbf09f758a42 100644 (file)
@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index c11981fed827deb3572f828ce0dc6f7dc39058cf..4ebdfbadeb9ce6160d7d7ea023b87cc6d13860c3 100644 (file)
@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 1366326474e5b664951ffe06944cfddccf140e9c..18f2abd7e2552e985d670551b1abc729c0d24d5f 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>                /* Initdata                       */
 #include <linux/ioport.h>      /* request_region                 */
 #include <linux/proc_fs.h>     /* radio card status report       */
+#include <linux/seq_file.h>
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
 static void typhoon_mute(struct typhoon_device *dev);
 static void typhoon_unmute(struct typhoon_device *dev);
 static int typhoon_setvol(struct typhoon_device *dev, int vol);
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
-#endif
 
 static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
 {
@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
+static int typhoon_proc_show(struct seq_file *m, void *v)
 {
-       char *out = buf;
-
        #ifdef MODULE
            #define MODULEPROCSTRING "Driver loaded as a module"
        #else
            #define MODULEPROCSTRING "Driver compiled into kernel"
        #endif
 
-       /* output must be kept under PAGE_SIZE */
-       out += sprintf(out, BANNER);
-       out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
-       out += sprintf(out, "frequency = %lu kHz\n",
+       seq_puts(m, BANNER);
+       seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
+       seq_printf(m, "frequency = %lu kHz\n",
                typhoon_unit.curfreq >> 4);
-       out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
-       out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
+       seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
+       seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
                "on" : "off");
-       out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
-       out += sprintf(out, "mute frequency = %lu kHz\n",
+       seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
+       seq_printf(m, "mute frequency = %lu kHz\n",
                typhoon_unit.mutefreq >> 4);
-       return out - buf;
+       return 0;
 }
 
+static int typhoon_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, typhoon_proc_show, NULL);
+}
+
+static const struct file_operations typhoon_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = typhoon_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
 
 MODULE_AUTHOR("Dr. Henrik Seidel");
@@ -404,7 +413,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
 module_param(radio_nr, int, 0);
 
 #ifdef MODULE
-static unsigned long mutefreq = 0;
+static unsigned long mutefreq;
 module_param(mutefreq, ulong, 0);
 MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
 #endif
@@ -450,8 +459,7 @@ static int __init typhoon_init(void)
        typhoon_mute(&typhoon_unit);
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-       if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
-                                   typhoon_get_info))
+       if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
                printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
 #endif
 
index 203f4373eeb8f7ea189cd3ef2705a1ba9c7f55c2..43773c56c62f0fcd45e25f87629591d51fb5d5ce 100644 (file)
@@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops =
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 1832966f53f3bee6b95e631ed248b61d30ef452c..fe9a4cc141414c18523cb11c1b97dd0138b8c111 100644 (file)
@@ -270,6 +270,15 @@ config VIDEO_SAA711X
          To compile this driver as a module, choose M here: the
          module will be called saa7115.
 
+config VIDEO_SAA717X
+       tristate "Philips SAA7171/3/4 audio/video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7171/3/4 audio/video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa717x.
+
 config VIDEO_SAA7191
        tristate "Philips SAA7191 video decoder"
        depends on VIDEO_V4L1 && I2C
@@ -689,6 +698,8 @@ source "drivers/media/video/cx88/Kconfig"
 
 source "drivers/media/video/cx23885/Kconfig"
 
+source "drivers/media/video/au0828/Kconfig"
+
 source "drivers/media/video/ivtv/Kconfig"
 
 config VIDEO_M32R_AR
@@ -836,4 +847,49 @@ config USB_STKWEBCAM
 
 endif # V4L_USB_DRIVERS
 
+config SOC_CAMERA
+       tristate "SoC camera support"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_DMA_SG
+       help
+         SoC Camera is a common API to several cameras, not connecting
+         over a bus like PCI or USB. For example some i2c camera connected
+         directly to the data bus of an SoC.
+
+config SOC_CAMERA_MT9M001
+       tristate "mt9m001 support"
+       depends on SOC_CAMERA
+       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+       help
+         This driver supports MT9M001 cameras from Micron, monochrome
+         and colour models.
+
+config MT9M001_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9m001"
+       depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
+       help
+         Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_MT9V022
+       tristate "mt9v022 support"
+       depends on SOC_CAMERA
+       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+       help
+         This driver supports MT9V022 cameras from Micron
+
+config MT9V022_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9v022"
+       depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
+       help
+         Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config VIDEO_PXA27x
+       tristate "PXA27x Quick Capture Interface driver"
+       depends on VIDEO_DEV && PXA27x
+       select SOC_CAMERA
+       ---help---
+         This is a v4l2 driver for the PXA27x Quick Capture Interface
+
 endif # VIDEO_CAPTURE_DRIVERS
index 3f209b32eeac01ec81d3f65693f0614b89c803b8..be14227f37269adb548577df17407aa52c6905ae 100644 (file)
@@ -4,7 +4,7 @@
 
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
-tuner-objs     :=      tuner-core.o tuner-types.o
+tuner-objs     :=      tuner-core.o
 
 msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
 
@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
 obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
 obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
 obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
@@ -87,6 +88,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 
 obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
 obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
+# tuner-types will be merged into tuner-simple, in the future
+obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
 obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
 obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
 obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
@@ -135,5 +138,12 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
+obj-$(CONFIG_VIDEO_PXA27x)     += pxa_camera.o
+obj-$(CONFIG_SOC_CAMERA)       += soc_camera.o
+obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828/
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index fea2e723e34b965da2853c58a9d2618d6f0a98f2..f794f2dbfb327be6c979baedcfd6decca8f3df67 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(x) (x)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 10d4d89623f15431080c3fda94b37164c4dc67fd..8ee07a68f7026527ed2eb4e5f8624955f27464d6 100644 (file)
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index c94a4d0f280475c987b306d9716596c35d9256b7..8c7d1958856b600f515c51716d960b2aaaf7f167 100644 (file)
@@ -125,8 +125,8 @@ static unsigned char        yuv[MAX_AR_FRAME_BYTES];
 /* default frequency */
 #define DEFAULT_FREQ   50      /* 50 or 75 (MHz) is available as BCLK */
 static int freq = DEFAULT_FREQ;        /* BCLK: available 50 or 70 (MHz) */
-static int vga = 0;            /* default mode(0:QVGA mode, other:VGA mode) */
-static int vga_interlace = 0;  /* 0 is normal mode for, else interlace mode */
+static int vga;                        /* default mode(0:QVGA mode, other:VGA mode) */
+static int vga_interlace;      /* 0 is normal mode for, else interlace mode */
 module_param(freq, int, 0);
 module_param(vga, int, 0);
 module_param(vga_interlace, int, 0);
@@ -747,7 +747,9 @@ static const struct file_operations ar_fops = {
        .release        = video_exclusive_release,
        .read           = ar_read,
        .ioctl          = ar_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
new file mode 100644 (file)
index 0000000..c97c4bd
--- /dev/null
@@ -0,0 +1,12 @@
+
+config VIDEO_AU0828
+       tristate "Auvitek AU0828 support"
+       depends on VIDEO_DEV && I2C && INPUT
+       select I2C_ALGOBIT
+       select DVB_AU8522 if !DVB_FE_CUSTOMIZE
+       select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       ---help---
+         This is a video4linux driver for Auvitek's USB device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called au0828
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
new file mode 100644 (file)
index 0000000..9f4f572
--- /dev/null
@@ -0,0 +1,9 @@
+au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
new file mode 100644 (file)
index 0000000..8ca91f8
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "au0828.h"
+#include "au0828-cards.h"
+
+struct au0828_board au0828_boards[] = {
+       [AU0828_BOARD_UNKNOWN] = {
+               .name   = "Unknown board",
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR850] = {
+               .name   = "Hauppauge HVR850",
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
+               .name   = "Hauppauge HVR950Q",
+       },
+       [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
+               .name   = "DViCO FusionHDTV USB",
+       },
+};
+const unsigned int au0828_bcount = ARRAY_SIZE(au0828_boards);
+
+/* Tuner callback function for au0828 boards. Currently only needed
+ * for HVR1500Q, which has an xc5000 tuner.
+ */
+int au0828_tuner_callback(void *priv, int command, int arg)
+{
+       struct au0828_dev *dev = priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               if (command == 0) {
+                       /* Tuner Reset Command from xc5000 */
+                       /* Drive the tuner into reset and out */
+                       au0828_clear(dev, REG_001, 2);
+                       mdelay(200);
+                       au0828_set(dev, REG_001, 2);
+                       mdelay(50);
+                       return 0;
+               } else {
+                       printk(KERN_ERR
+                               "%s(): Unknown command.\n", __func__);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       return 0; /* Should never be here */
+}
+
+static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
+       case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                      "unknown hauppauge model #%d\n", __func__, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+              __func__, tv.model);
+}
+
+void au0828_card_setup(struct au0828_dev *dev)
+{
+       static u8 eeprom[256];
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dev->i2c_rc == 0) {
+               dev->i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
+       }
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+               if (dev->i2c_rc == 0)
+                       hauppauge_eeprom(dev, eeprom+0xa0);
+               break;
+       }
+}
+
+/*
+ * The bridge has between 8 and 12 gpios.
+ * Regs 1 and 0 deal with output enables.
+ * Regs 3 and 2 deal with direction.
+ */
+void au0828_gpio_setup(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+               /* GPIO's
+                * 4 - CS5340
+                * 5 - AU8522 Demodulator
+                * 6 - eeprom W/P
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0x88 | 0x20);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_002, 0x88 | 0x20);
+               au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
+               msleep(250);
+               break;
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               /* GPIO's
+                * 6 - ?
+                * 8 - AU8522 Demodulator
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_000, 0xa0);
+               msleep(250);
+               break;
+       }
+}
+
+/* table of devices that work with this driver */
+struct usb_device_id au0828_usb_id_table [] = {
+       { USB_DEVICE(0x2040, 0x7200),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7240),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
+       { USB_DEVICE(0x0fe9, 0xd620),
+               .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
+       { },
+};
+
+MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
new file mode 100644 (file)
index 0000000..e26f54a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define AU0828_BOARD_UNKNOWN           0
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
+#define AU0828_BOARD_HAUPPAUGE_HVR850  2
+#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
new file mode 100644 (file)
index 0000000..e65d564
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/mutex.h>
+
+#include "au0828.h"
+
+/*
+ * 1 = General debug messages
+ * 2 = USB handling
+ * 4 = I2C related
+ * 8 = Bridge related
+ */
+unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+unsigned int usb_debug;
+module_param(usb_debug, int, 0644);
+MODULE_PARM_DESC(usb_debug, "enable usb debug messages");
+
+unsigned int bridge_debug;
+module_param(bridge_debug, int, 0644);
+MODULE_PARM_DESC(bridge_debug, "enable bridge debug messages");
+
+#define _AU0828_BULKPIPE 0x03
+#define _BULKPIPESIZE 0xffff
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size);
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size);
+
+/* USB Direction */
+#define CMD_REQUEST_IN         0x00
+#define CMD_REQUEST_OUT                0x01
+
+u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
+{
+       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
+       dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
+       return dev->ctrlmsg[0];
+}
+
+u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
+{
+       dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
+       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
+                               dev->ctrlmsg, 0);
+}
+
+static void cmd_msg_dump(struct au0828_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
+               dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
+                               "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+                       __func__,
+                       dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
+                       dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
+                       dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
+                       dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
+                       dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
+                       dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
+                       dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
+                       dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
+}
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size)
+{
+       int status = -ENODEV;
+       mutex_lock(&dev->mutex);
+       if (dev->usbdev) {
+
+               /* cp must be memory that has been allocated by kmalloc */
+               status = usb_control_msg(dev->usbdev,
+                               usb_sndctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index,
+                               cp, size, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
+                               __func__, status);
+               }
+
+       }
+       mutex_unlock(&dev->mutex);
+       return status;
+}
+
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size)
+{
+       int status = -ENODEV;
+       mutex_lock(&dev->mutex);
+       if (dev->usbdev) {
+
+               memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
+
+               /* cp must be memory that has been allocated by kmalloc */
+               status = usb_control_msg(dev->usbdev,
+                               usb_rcvctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index,
+                               cp, size, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
+                               __func__, status);
+               } else
+                       cmd_msg_dump(dev);
+       }
+       mutex_unlock(&dev->mutex);
+       return status;
+}
+
+static void au0828_usb_disconnect(struct usb_interface *interface)
+{
+       struct au0828_dev *dev = usb_get_intfdata(interface);
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Digital TV */
+       au0828_dvb_unregister(dev);
+
+       /* I2C */
+       au0828_i2c_unregister(dev);
+
+       usb_set_intfdata(interface, NULL);
+
+       mutex_lock(&dev->mutex);
+       dev->usbdev = NULL;
+       mutex_unlock(&dev->mutex);
+
+       kfree(dev);
+
+}
+
+static int au0828_usb_probe(struct usb_interface *interface,
+       const struct usb_device_id *id)
+{
+       int ifnum;
+       struct au0828_dev *dev;
+       struct usb_device *usbdev = interface_to_usbdev(interface);
+
+       ifnum = interface->altsetting->desc.bInterfaceNumber;
+
+       if (ifnum != 0)
+               return -ENODEV;
+
+       dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
+               le16_to_cpu(usbdev->descriptor.idVendor),
+               le16_to_cpu(usbdev->descriptor.idProduct),
+               ifnum);
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       mutex_init(&dev->mutex);
+       mutex_init(&dev->dvb.lock);
+       dev->usbdev = usbdev;
+       dev->board = id->driver_info;
+
+       usb_set_intfdata(interface, dev);
+
+       /* Power Up the bridge */
+       au0828_write(dev, REG_600, 1 << 4);
+
+       /* Bring up the GPIO's and supporting devices */
+       au0828_gpio_setup(dev);
+
+       /* I2C */
+       au0828_i2c_register(dev);
+
+       /* Setup */
+       au0828_card_setup(dev);
+
+       /* Digital TV */
+       au0828_dvb_register(dev);
+
+       printk(KERN_INFO "Registered device AU0828 [%s]\n",
+               au0828_boards[dev->board].name == NULL ? "Unset" :
+               au0828_boards[dev->board].name);
+
+       return 0;
+}
+
+static struct usb_driver au0828_usb_driver = {
+       .name           = DRIVER_NAME,
+       .probe          = au0828_usb_probe,
+       .disconnect     = au0828_usb_disconnect,
+       .id_table       = au0828_usb_id_table,
+};
+
+static int __init au0828_init(void)
+{
+       int ret;
+
+       if (debug)
+               printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
+
+       if (usb_debug) {
+               printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
+               debug |= 2;
+       }
+
+       if (i2c_debug) {
+               printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
+               debug |= 4;
+       }
+
+       if (bridge_debug) {
+               printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
+                      __func__);
+               debug |= 8;
+       }
+
+       printk(KERN_INFO "au0828 driver loaded\n");
+
+       ret = usb_register(&au0828_usb_driver);
+       if (ret)
+               printk(KERN_ERR "usb_register failed, error = %d\n", ret);
+
+       return ret;
+}
+
+static void __exit au0828_exit(void)
+{
+       usb_deregister(&au0828_usb_driver);
+}
+
+module_init(au0828_init);
+module_exit(au0828_exit);
+
+MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
+MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
new file mode 100644 (file)
index 0000000..85d0ae9
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <media/v4l2-common.h>
+
+#include "au0828.h"
+#include "au8522.h"
+#include "xc5000.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define _AU0828_BULKPIPE 0x83
+#define _BULKPIPESIZE 0xe522
+
+static struct au8522_config hauppauge_hvr950q_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+};
+
+static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
+       .i2c_address      = 0x61,
+       .if_khz           = 6000,
+       .tuner_callback   = au0828_tuner_callback
+};
+
+/*-------------------------------------------------------------------*/
+static void urb_completion(struct urb *purb)
+{
+       u8 *ptr;
+       struct au0828_dev *dev = purb->context;
+       int ptype = usb_pipetype(purb->pipe);
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (!dev)
+               return;
+
+       if (dev->urb_streaming == 0)
+               return;
+
+       if (ptype != PIPE_BULK) {
+               printk(KERN_ERR "%s() Unsupported URB type %d\n",
+                      __func__, ptype);
+               return;
+       }
+
+       ptr = (u8 *)purb->transfer_buffer;
+
+       /* Feed the transport payload into the kernel demux */
+       dvb_dmx_swfilter_packets(&dev->dvb.demux,
+               purb->transfer_buffer, purb->actual_length / 188);
+
+       /* Clean the buffer before we requeue */
+       memset(purb->transfer_buffer, 0, URB_BUFSIZE);
+
+       /* Requeue URB */
+       usb_submit_urb(purb, GFP_ATOMIC);
+}
+
+static int stop_urb_transfer(struct au0828_dev *dev)
+{
+       int i;
+
+       dprintk(2, "%s()\n", __func__);
+
+       for (i = 0; i < URB_COUNT; i++) {
+               usb_kill_urb(dev->urbs[i]);
+               kfree(dev->urbs[i]->transfer_buffer);
+               usb_free_urb(dev->urbs[i]);
+       }
+
+       dev->urb_streaming = 0;
+
+       return 0;
+}
+
+static int start_urb_transfer(struct au0828_dev *dev)
+{
+       struct urb *purb;
+       int i, ret = -ENOMEM;
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (dev->urb_streaming) {
+               dprintk(2, "%s: iso xfer already running!\n", __func__);
+               return 0;
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+
+               dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->urbs[i])
+                       goto err;
+
+               purb = dev->urbs[i];
+
+               purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
+               if (!purb->transfer_buffer) {
+                       usb_free_urb(purb);
+                       dev->urbs[i] = 0;
+                       goto err;
+               }
+
+               purb->status = -EINPROGRESS;
+               usb_fill_bulk_urb(purb,
+                                 dev->usbdev,
+                                 usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+                                 purb->transfer_buffer,
+                                 URB_BUFSIZE,
+                                 urb_completion,
+                                 dev);
+
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+               ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
+               if (ret != 0) {
+                       stop_urb_transfer(dev);
+                       printk(KERN_ERR "%s: failed urb submission, "
+                              "err = %d\n", __func__, ret);
+                       return ret;
+               }
+       }
+
+       dev->urb_streaming = 1;
+       ret = 0;
+
+err:
+       return ret;
+}
+
+static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (dvb->feeding++ == 0) {
+                       /* Start transport */
+                       au0828_write(dev, 0x608, 0x90);
+                       au0828_write(dev, 0x609, 0x72);
+                       au0828_write(dev, 0x60a, 0x71);
+                       au0828_write(dev, 0x60b, 0x01);
+                       ret = start_urb_transfer(dev);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (--dvb->feeding == 0) {
+                       /* Stop transport */
+                       au0828_write(dev, 0x608, 0x00);
+                       au0828_write(dev, 0x609, 0x00);
+                       au0828_write(dev, 0x60a, 0x00);
+                       au0828_write(dev, 0x60b, 0x00);
+                       ret = stop_urb_transfer(dev);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+int dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int result;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
+                                     &dev->usbdev->dev, adapter_nr);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_adapter failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_adapter;
+       }
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_frontend failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dev;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = au0828_dvb_start_feed;
+       dvb->demux.stop_feed  = au0828_dvb_stop_feed;
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+void au0828_dvb_unregister(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb->frontend == NULL)
+               return;
+
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+int au0828_dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* init frontend */
+       switch (dev->board) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL) {
+                       hauppauge_hvr950q_tunerconfig.priv = dev;
+                       dvb_attach(xc5000_attach, dvb->frontend,
+                               &dev->i2c_adap,
+                               &hauppauge_hvr950q_tunerconfig);
+               }
+               break;
+       default:
+               printk(KERN_WARNING "The frontend of your DVB/ATSC card "
+                      "isn't supported yet\n");
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR "%s() Frontend initialization failed\n",
+                      __func__);
+               return -1;
+       }
+
+       /* Put the analog decoder in standby to keep it quiet */
+       au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
+
+       if (dvb->frontend->ops.analog_ops.standby)
+               dvb->frontend->ops.analog_ops.standby(dvb->frontend);
+
+       /* register everything */
+       ret = dvb_register(dev);
+       if (ret < 0) {
+               if (dvb->frontend->ops.release)
+                       dvb->frontend->ops.release(dvb->frontend);
+               return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
new file mode 100644 (file)
index 0000000..94c8b74
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "au0828.h"
+
+#include <media/v4l2-common.h>
+
+unsigned int i2c_debug;
+module_param(i2c_debug, int, 0444);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define I2C_WAIT_DELAY 512
+#define I2C_WAIT_RETRY 64
+
+static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
+}
+
+static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
+}
+
+static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_slave_did_read_ack(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
+}
+
+static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_read_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
+}
+
+static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (i2c_is_write_done(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined_rlen)
+{
+       int i, strobe = 0;
+       struct au0828_dev *dev = i2c_adap->algo_data;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, REG_2FF, 0x01);
+       au0828_write(dev, REG_202, 0x07);
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, REG_203, msg->addr << 1);
+
+       dprintk(4, "SEND: %02x\n", msg->addr);
+
+       for (i = 0; i < msg->len;) {
+
+               dprintk(4, " %02x\n", msg->buf[i]);
+
+               au0828_write(dev, REG_205, msg->buf[i]);
+
+               strobe++;
+               i++;
+
+               if ((strobe >= 4) || (i >= msg->len)) {
+
+                       /* Strobe the byte into the bus */
+                       if (i < msg->len)
+                               au0828_write(dev, REG_200, 0x41);
+                       else
+                               au0828_write(dev, REG_200, 0x01);
+
+                       /* Reset strobe trigger */
+                       strobe = 0;
+
+                       if (!i2c_wait_write_done(i2c_adap))
+                               return -EIO;
+
+               }
+
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       int i;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, REG_2FF, 0x01);
+       au0828_write(dev, REG_202, 0x07);
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, REG_203, msg->addr << 1);
+
+       dprintk(4, " RECV:\n");
+
+       /* Deal with i2c_scan */
+       if (msg->len == 0) {
+               au0828_write(dev, REG_200, 0x20);
+               if (i2c_wait_read_ack(i2c_adap))
+                       return -EIO;
+               return 0;
+       }
+
+       for (i = 0; i < msg->len;) {
+
+               i++;
+
+               if (i < msg->len)
+                       au0828_write(dev, REG_200, 0x60);
+               else
+                       au0828_write(dev, REG_200, 0x20);
+
+               if (!i2c_wait_read_done(i2c_adap))
+                       return -EIO;
+
+               msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
+
+               dprintk(4, " %02x\n", msg->buf[i-1]);
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+                   struct i2c_msg *msgs, int num)
+{
+       int i, retval = 0;
+
+       dprintk(4, "%s(num = %d)\n", __func__, num);
+
+       for (i = 0; i < num; i++) {
+               dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+                       __func__, num, msgs[i].addr, msgs[i].len);
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read */
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+                       /* write then read from same address */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i],
+                                              msgs[i + 1].len);
+                       if (retval < 0)
+                               goto err;
+                       i++;
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+               } else {
+                       /* write */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+               }
+               if (retval < 0)
+                       goto err;
+       }
+       return num;
+
+err:
+       return retval;
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+       dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
+               client->driver->driver.name, client->addr, client->name);
+
+       if (!client->driver->command)
+               return 0;
+
+       return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+       dprintk(1, "i2c detach [client=%s]\n", client->name);
+
+       return 0;
+}
+
+void au0828_call_i2c_clients(struct au0828_dev *dev,
+                             unsigned int cmd, void *arg)
+{
+       if (dev->i2c_rc != 0)
+               return;
+
+       i2c_clients_command(&dev->i2c_adap, cmd, arg);
+}
+
+static u32 au0828_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au0828_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = au0828_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter au0828_i2c_adap_template = {
+       .name              = DRIVER_NAME,
+       .owner             = THIS_MODULE,
+       .id                = I2C_HW_B_AU0828,
+       .algo              = &au0828_i2c_algo_template,
+       .class             = I2C_CLASS_TV_ANALOG,
+       .client_register   = attach_inform,
+       .client_unregister = detach_inform,
+};
+
+static struct i2c_client au0828_i2c_client_template = {
+       .name   = "au0828 internal",
+};
+
+static char *i2c_devs[128] = {
+       [0x8e >> 1] = "au8522",
+       [0xa0 >> 1] = "eeprom",
+       [0xc2 >> 1] = "tuner/xc5000",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i, rc;
+
+       for (i = 0; i < 128; i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c, &buf, 0);
+               if (rc < 0)
+                       continue;
+               printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
+                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+}
+
+/* init + register i2c algo-bit adapter */
+int au0828_i2c_register(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
+              sizeof(dev->i2c_adap));
+       memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
+              sizeof(dev->i2c_algo));
+       memcpy(&dev->i2c_client, &au0828_i2c_client_template,
+              sizeof(dev->i2c_client));
+
+       dev->i2c_adap.dev.parent = &dev->usbdev->dev;
+
+       strlcpy(dev->i2c_adap.name, DRIVER_NAME,
+               sizeof(dev->i2c_adap.name));
+
+       dev->i2c_algo.data = dev;
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, dev);
+       i2c_add_adapter(&dev->i2c_adap);
+
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       if (0 == dev->i2c_rc) {
+               printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
+               if (i2c_scan)
+                       do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
+       } else
+               printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
+
+       return dev->i2c_rc;
+}
+
+int au0828_i2c_unregister(struct au0828_dev *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
+
diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
new file mode 100644 (file)
index 0000000..3982755
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* We'll start to rename these registers once we have a better
+ * understanding of their meaning.
+ */
+#define REG_000 0x000
+#define REG_001 0x001
+#define REG_002 0x002
+#define REG_003 0x003
+
+#define REG_200 0x200
+#define REG_201 0x201
+#define REG_202 0x202
+#define REG_203 0x203
+#define REG_205 0x205
+#define REG_209 0x209
+#define REG_2FF 0x2ff
+
+#define REG_600 0x600
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
new file mode 100644 (file)
index 0000000..0200b9f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <media/tveeprom.h>
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#include "au0828-reg.h"
+#include "au0828-cards.h"
+
+#define DRIVER_NAME "au0828"
+#define URB_COUNT   16
+#define URB_BUFSIZE (0xe522)
+
+struct au0828_board {
+       char *name;
+};
+
+struct au0828_dvb {
+       struct mutex lock;
+       struct dvb_adapter adapter;
+       struct dvb_frontend *frontend;
+       struct dvb_demux demux;
+       struct dmxdev dmxdev;
+       struct dmx_frontend fe_hw;
+       struct dmx_frontend fe_mem;
+       struct dvb_net net;
+       int feeding;
+};
+
+struct au0828_dev {
+       struct mutex mutex;
+       struct usb_device       *usbdev;
+       int                     board;
+       u8                      ctrlmsg[64];
+
+       /* I2C */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_algo_bit_data        i2c_algo;
+       struct i2c_client               i2c_client;
+       u32                             i2c_rc;
+
+       /* Digital */
+       struct au0828_dvb               dvb;
+
+       /* USB / URB Related */
+       int             urb_streaming;
+       struct urb      *urbs[URB_COUNT];
+
+};
+
+struct au0828_buff {
+       struct au0828_dev       *dev;
+       struct urb              *purb;
+       struct list_head        buff_list;
+};
+
+/* ----------------------------------------------------------- */
+#define au0828_read(dev, reg) au0828_readreg(dev, reg)
+#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
+#define au0828_andor(dev, reg, mask, value)                            \
+        au0828_writereg(dev, reg,                                      \
+       (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
+
+#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
+#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* au0828-core.c */
+extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
+extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
+extern unsigned int debug;
+extern unsigned int usb_debug;
+extern unsigned int bridge_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-cards.c */
+extern struct au0828_board au0828_boards[];
+extern struct usb_device_id au0828_usb_id_table[];
+extern const unsigned int au0828_bcount;
+extern void au0828_gpio_setup(struct au0828_dev *dev);
+extern int au0828_tuner_callback(void *priv, int command, int arg);
+extern void au0828_card_setup(struct au0828_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* au0828-i2c.c */
+extern int au0828_i2c_register(struct au0828_dev *dev);
+extern int au0828_i2c_unregister(struct au0828_dev *dev);
+extern void au0828_call_i2c_clients(struct au0828_dev *dev,
+       unsigned int cmd, void *arg);
+extern unsigned int i2c_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-dvb.c */
+extern int au0828_dvb_register(struct au0828_dev *dev);
+extern void au0828_dvb_unregister(struct au0828_dev *dev);
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug & level)\
+               printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
+       } while (0)
index e663cc045c41c7a1748145b0b78f7ea41860c628..8bfd5c75cb3a736b04218cb697a870c8d5ab936d 100644 (file)
@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 7dee2e3235ad5619a735c0c74db3c4c67d25cd32..98ee2d8feb34ecbcb5282112e1b49a0e7b5957f6 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 7374c02dd183fc1a5d457b8899828dab9c195dd8..f20a01cfc73e442dea087f4962c09cad5f603a12 100644 (file)
@@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv);
 static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
 static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
 
+static void geovision_muxsel(struct bttv *btv, unsigned int input);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -301,6 +303,7 @@ static struct CARD {
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
        { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
        { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,    "DViCO FusionHDTV 2" },
+       { 0x763c008a, BTTV_BOARD_GEOVISION_GV600,       "GeoVision GV-600" },
 
        { 0, -1, NULL }
 };
@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
                .needs_tvaudio  = 1,
                .pll            = PLL_28,
                .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
        },
        [BTTV_BOARD_WINVIEW_601] = {
                .name           = "Leadtek WinView 601",
@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
                .tuner          = 0,
                .svhs           = 2,
                .muxsel         = { 2, 3, 1, 0 },
-               .tuner_type     = TUNER_PHILIPS_ATSC,
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .has_dvb        = 1,
@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
        [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
                .name           = "DViCO FusionHDTV 2",
                .tuner          = 0,
-               .tuner_type     = TUNER_PHILIPS_ATSC, /* FCV1236D */
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .video_inputs   = 3,
@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
        },
+       [BTTV_BOARD_GEOVISION_GV600] = {
+               /* emhn@usb.ve */
+               .name             = "Geovision GV-600",
+               .video_inputs     = 16,
+               .audio_inputs     = 0,
+               .tuner            = UNSET,
+               .svhs             = UNSET,
+               .gpiomask         = 0x0,
+               .muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
+                                     2, 2, 2, 2, 2, 2, 2, 2 },
+               .muxsel_hook      = geovision_muxsel,
+               .gpiomux          = { 0 },
+               .no_msp34xx       = 1,
+               .pll              = PLL_28,
+               .tuner_type       = UNSET,
+               .tuner_addr       = ADDR_UNSET,
+               .radio_addr       = ADDR_UNSET,
+       },
+       [BTTV_BOARD_KOZUMI_KTV_01C] = {
+               /* Mauro Lacy <mauro@lacy.com.ar>
+                * Based on MagicTV and Conceptronic CONTVFMi */
+
+               .name           = "Kozumi KTV-01C",
+               .video_inputs   = 3,
+               .audio_inputs   = 1,
+               .tuner          = 0,
+               .svhs           = 2,
+               .gpiomask       = 0x008007,
+               .muxsel         = { 2, 3, 1, 1 },
+               .gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
+               .gpiomute       = 3, /* CONTVFMi */
+               .needs_tvaudio  = 0,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
 };
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3331,6 +3375,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
        gpio_bits( 3<<9, inmux<<9 );
 }
 
+static void geovision_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int inmux = input % 16;
+       gpio_inout(0xf, 0xf);
+       gpio_bits(0xf, inmux);
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void bttv_reset_audio(struct bttv *btv)
index fcf8f2d208a843890df86252ee7579f52cfb385e..2ca3e9cfb2bbbaf0887e70e23624268002e328f5 100644 (file)
@@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
        if (check_btres(fh, RESOURCE_OVERLAY)) {
                struct bttv_buffer *new;
 
-               new = videobuf_pci_alloc(sizeof(*new));
+               new = videobuf_sg_alloc(sizeof(*new));
                new->crop = btv->crop[!!fh->do_crop].rect;
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
@@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
        mutex_lock(&fh->cap.vb_lock);
        if (on) {
                fh->ov.tvnorm = btv->tvnorm;
-               new = videobuf_pci_alloc(sizeof(*new));
+               new = videobuf_sg_alloc(sizeof(*new));
                new->crop = btv->crop[!!fh->do_crop].rect;
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
        } else {
@@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
                if (check_btres(fh, RESOURCE_OVERLAY)) {
                        struct bttv_buffer *new;
 
-                       new = videobuf_pci_alloc(sizeof(*new));
+                       new = videobuf_sg_alloc(sizeof(*new));
                        new->crop = btv->crop[!!fh->do_crop].rect;
                        bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                        retval = bttv_switch_overlay(btv, fh, new);
@@ -3117,12 +3117,18 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
 static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        strcpy(a->name, "audio");
        return 0;
 }
 
 static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -3184,7 +3190,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                        /* need to capture a new frame */
                        if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
                                goto err;
-                       fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
+                       fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
                        if (NULL == fh->cap.read_buf)
                                goto err;
                        fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
@@ -3251,14 +3257,14 @@ static int bttv_open(struct inode *inode, struct file *file)
        fh->ov.setup_ok = 0;
        v4l2_prio_open(&btv->prio,&fh->prio);
 
-       videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
-                           btv->c.pci, &btv->s_lock,
+       videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct bttv_buffer),
                            fh);
-       videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
-                           btv->c.pci, &btv->s_lock,
+       videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct bttv_buffer),
@@ -3457,6 +3463,9 @@ static int radio_release(struct inode *inode, struct file *file)
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
+       file->private_data = NULL;
+       kfree(fh);
+
        btv->radio_user--;
 
        bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
@@ -3510,7 +3519,7 @@ static int radio_enum_input(struct file *file, void *priv,
                return -EINVAL;
 
        strcpy(i->name, "Radio");
-        i->type = V4L2_INPUT_TYPE_TUNER;
+       i->type = V4L2_INPUT_TYPE_TUNER;
 
        return 0;
 }
@@ -3518,10 +3527,9 @@ static int radio_enum_input(struct file *file, void *priv,
 static int radio_g_audio(struct file *file, void *priv,
                                        struct v4l2_audio *a)
 {
-       if (a->index != 0)
+       if (unlikely(a->index))
                return -EINVAL;
 
-       memset(a, 0, sizeof(*a));
        strcpy(a->name, "Radio");
 
        return 0;
@@ -3543,11 +3551,17 @@ static int radio_s_tuner(struct file *file, void *priv,
 static int radio_s_audio(struct file *file, void *priv,
                                        struct v4l2_audio *a)
 {
+       if (unlikely(a->index))
+               return -EINVAL;
+
        return 0;
 }
 
 static int radio_s_input(struct file *filp, void *priv, unsigned int i)
 {
+       if (unlikely(i))
+               return -EINVAL;
+
        return 0;
 }
 
index fc9ecb21eec6e66311e773126f93f3ab74bfe582..a38af98f4cae9e33ad4f47cd1873407a47c34dab 100644 (file)
@@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv)
                ir->mask_keyup   = 0x004000;
                ir->polling      = 50; /* ms */
                break;
+       case BTTV_BOARD_KOZUMI_KTV_01C:
+               ir_codes         = ir_codes_pctv_sedna;
+               ir->mask_keycode = 0x001f00;
+               ir->mask_keyup   = 0x006000;
+               ir->polling      = 50; /* ms */
+               break;
        }
        if (NULL == ir_codes) {
                dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
index 75fa82c7c7351179ef5120a17d487f0e0cb43ae0..bfdbc469e30f379e6e75bdf4a2abaf63fcc28c4d 100644 (file)
@@ -54,7 +54,7 @@
 #define VBI_DEFLINES 16
 
 static unsigned int vbibufs = 4;
-static unsigned int vbi_debug = 0;
+static unsigned int vbi_debug;
 
 module_param(vbibufs,   int, 0444);
 module_param(vbi_debug, int, 0644);
index bf4c339a520c879d5bf1a04e5c213d6a63f2cc5a..f2393202904b795a6528fab8745ea821b7627c6a 100644 (file)
@@ -19,6 +19,7 @@
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/i2c-addr.h>
+#include <media/tuner.h>
 
 /* ---------------------------------------------------------- */
 /* exported by bttv-cards.c                                   */
 #define BTTV_BOARD_VOODOOTV_200                   0x93
 #define BTTV_BOARD_DVICO_FUSIONHDTV_2     0x94
 #define BTTV_BOARD_TYPHOON_TVTUNERPCI     0x95
+#define BTTV_BOARD_GEOVISION_GV600        0x96
+#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
 
 
 /* more card-specific defines */
index 1305d315cfc50227445b952fda59b009b7b3af0d..03816b73f847560571a1bccd3693bdc5502d1666 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <linux/device.h>
 #include <media/videobuf-dma-sg.h>
-#include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/ir-common.h>
 
index 032265383df25203eabf1816a8a94f4bf43daa2d..b364adaae78d8e8262043a5e2c3734249ca01c51 100644 (file)
@@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
        int ret=1;
        unsigned int hi, lo;
        unsigned int hi2, lo2;
-       static int state = 0;
+       static int state;
 
        if (buffer == NULL)
        {
@@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = qcam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = qcam_read,
        .llseek         = no_llseek,
 };
@@ -912,7 +914,7 @@ static struct video_device qcam_template=
 
 #define MAX_CAMS 4
 static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams = 0;
+static unsigned int num_cams;
 
 static int init_bwqcam(struct parport *port)
 {
index cf1546b5a7f1b33e8f8f7d8e865fa54f4fe518e5..fe1e67bb1ca860b6a946afb0ed6804654c8bf4ce 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <linux/mutex.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 
@@ -69,7 +70,7 @@ struct qcam_device {
 
 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 static int probe = 2;
-static int force_rgb = 0;
+static int force_rgb;
 static int video_nr = -1;
 
 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
@@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready1(qcam) == value)
                        return 0;
 
@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready2(qcam) == value)
                        return 0;
 
@@ -689,7 +692,9 @@ static const struct file_operations qcam_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = qcam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = qcam_read,
        .llseek         = no_llseek,
 };
@@ -741,7 +746,7 @@ static struct qcam_device *qcam_init(struct parport *port)
 }
 
 static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams = 0;
+static unsigned int num_cams;
 
 static int init_cqcam(struct parport *port)
 {
index 7ae499c9c54c8785e497e9ddabdcde740c017f01..5195b1f3378a627d60dd66452033ae1f2e56f353 100644 (file)
@@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video");
  */
 
 #define MAX_DMA_BUFS 3
-static int alloc_bufs_at_read = 0;
+static int alloc_bufs_at_read;
 module_param(alloc_bufs_at_read, bool, 0444);
 MODULE_PARM_DESC(alloc_bufs_at_read,
                "Non-zero value causes DMA buffers to be allocated when the "
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers,
                "will be allowed to allocate.  These buffers are big and live "
                "in vmalloc space.");
 
-static int flip = 0;
+static int flip;
 module_param(flip, bool, 0444);
 MODULE_PARM_DESC(flip,
                "If set, the sensor will be instructed to flip the image "
index 7c630f5ee7258faccf51b06180c76859e5f502da..2a81376ef5038dadaf621e2441588bab05eed4c6 100644 (file)
@@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = {
        .read           = cpia_read,
        .mmap           = cpia_mmap,
        .ioctl          = cpia_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 78392fb6f94ea3dd8b430f338024b73d86a5842c..5096058bf5793a68b3ea69d748913cd34caaa3e6 100644 (file)
@@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam);
 /* ErrorCode */
 #define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
 #define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
+#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
 
 #ifdef _CPIA_DEBUG_
 #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
+#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
 #else
 #define DBG(fmn,args...) do {} while(0)
 #endif
index a76bd786cf13474f3f16c5f2282f050f3bb39e4e..c8b9fdb700ff123138790e58452f4953dd3ef52b 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
-//#define _CPIA2_DEBUG_
+/* #define _CPIA2_DEBUG_ */
 
 #include "cpia2patch.h"
 
@@ -48,7 +48,7 @@ static const char *block_name[] = {
 };
 #endif
 
-static unsigned int debugs_on = 0;//DEBUG_REG;
+static unsigned int debugs_on; /* default 0 - DEBUG_REG */
 
 
 /******************************************************************************
@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
                            block_name[block_index]);
                break;
        default:
-               LOG("%s: invalid request mode\n",__FUNCTION__);
+               LOG("%s: invalid request mode\n",__func__);
                return -EINVAL;
        }
 
@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
                        frame_rate = CPIA2_VP_FRAMERATE_30;
                break;
        default:
-               LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
+               LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
                    cam->params.version.sensor_flags);
                return -EINVAL;
        }
@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
        }
 
        if (!buf) {
-               ERR("%s: buffer NULL\n",__FUNCTION__);
+               ERR("%s: buffer NULL\n",__func__);
                return -EINVAL;
        }
 
        if (!cam) {
-               ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
+               ERR("%s: Internal error, camera_data NULL!\n",__func__);
                return -EINVAL;
        }
 
@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
                return -ERESTARTSYS;
 
        if (!cam->present) {
-               LOG("%s: camera removed\n",__FUNCTION__);
+               LOG("%s: camera removed\n",__func__);
                mutex_unlock(&cam->busy_lock);
                return 0;       /* EOF */
        }
@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
        unsigned int status=0;
 
        if(!cam) {
-               ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
+               ERR("%s: Internal error, camera_data not found!\n",__func__);
                return POLLERR;
        }
 
index d8e929863a88d9305ecaefff2b8378fd06b9d374..a4574740350df30cf6bd3cb84592b8c84d39f779 100644 (file)
@@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = {
  *****************************************************************************/
 static void process_frame(struct camera_data *cam)
 {
-       static int frame_count = 0;
+       static int frame_count;
 
        unsigned char *inbuff = cam->workbuff->data;
 
index e378abec806d21ddb75145ed7bb788bc620b57fc..7ce2789fa976213188419ced61d709339fbf134e 100644 (file)
@@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = {
        .poll           = cpia2_v4l_poll,
        .ioctl          = cpia2_ioctl,
        .llseek         = no_llseek,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .mmap           = cpia2_mmap,
 };
 
index 9da4726eb9b981a21250565bbaaa8ed190052c3b..ef1f89399983549adc9192a9f9fd79259abcdc97 100644 (file)
@@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb)
        /* resubmit */
        urb->dev = ucpia->dev;
        if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
-               printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__,  i);
+               printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__,  i);
 }
 
 static int cpia_usb_open(void *privdata)
index 1fd326fe41136cd271717eb9b89582701782131f..ca5fbce3a9095bc07dca912ce74e19387f5a4f02 100644 (file)
@@ -8,6 +8,7 @@ config VIDEO_CX23885
        select VIDEO_TVEEPROM
        select VIDEO_IR
        select VIDEOBUF_DVB
+       select VIDEO_CX25840
        select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
@@ -16,6 +17,7 @@ config VIDEO_CX23885
        select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
        select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
        select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Conexant 23885 based
          TV cards.
index 32c90be506029374d8e901c82938ec64b12390a1..d7b0721af062611215e6b516ec5c86e970911414 100644 (file)
@@ -1,4 +1,4 @@
-cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
+cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
new file mode 100644 (file)
index 0000000..acdd3b6
--- /dev/null
@@ -0,0 +1,1764 @@
+/*
+ *
+ *  Support for a cx23417 mpeg encoder via cx23885 host port.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.8m.com>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *    (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *      - CX23885/7/8 support
+ *
+ *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx2341x.h>
+
+#include "cx23885.h"
+#include "media/cx2341x.h"
+
+#define CX23885_FIRM_IMAGE_SIZE 376836
+#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
+
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs, int, 0644);
+MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+static unsigned int mpeglines = 32;
+module_param(mpeglines, int, 0644);
+MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+static unsigned int mpeglinesize = 512;
+module_param(mpeglinesize, int, 0644);
+MODULE_PARM_DESC(mpeglinesize,
+       "number of bytes in each line of an MPEG buffer, range 512-1024");
+
+static unsigned int v4l_debug;
+module_param(v4l_debug, int, 0644);
+MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (v4l_debug >= level) \
+               printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
+       } while (0)
+
+static struct cx23885_tvnorm cx23885_tvnorms[] = {
+       {
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
+       }, {
+               .name      = "NTSC-JP",
+               .id        = V4L2_STD_NTSC_M_JP,
+       }, {
+               .name      = "PAL-BG",
+               .id        = V4L2_STD_PAL_BG,
+       }, {
+               .name      = "PAL-DK",
+               .id        = V4L2_STD_PAL_DK,
+       }, {
+               .name      = "PAL-I",
+               .id        = V4L2_STD_PAL_I,
+       }, {
+               .name      = "PAL-M",
+               .id        = V4L2_STD_PAL_M,
+       }, {
+               .name      = "PAL-N",
+               .id        = V4L2_STD_PAL_N,
+       }, {
+               .name      = "PAL-Nc",
+               .id        = V4L2_STD_PAL_Nc,
+       }, {
+               .name      = "PAL-60",
+               .id        = V4L2_STD_PAL_60,
+       }, {
+               .name      = "SECAM-L",
+               .id        = V4L2_STD_SECAM_L,
+       }, {
+               .name      = "SECAM-DK",
+               .id        = V4L2_STD_SECAM_DK,
+       }
+};
+
+/* ------------------------------------------------------------------ */
+enum cx23885_capture_type {
+       CX23885_MPEG_CAPTURE,
+       CX23885_RAW_CAPTURE,
+       CX23885_RAW_PASSTHRU_CAPTURE
+};
+enum cx23885_capture_bits {
+       CX23885_RAW_BITS_NONE             = 0x00,
+       CX23885_RAW_BITS_YUV_CAPTURE      = 0x01,
+       CX23885_RAW_BITS_PCM_CAPTURE      = 0x02,
+       CX23885_RAW_BITS_VBI_CAPTURE      = 0x04,
+       CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+       CX23885_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum cx23885_capture_end {
+       CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
+       CX23885_END_NOW, /* stop immediately, no irq */
+};
+enum cx23885_framerate {
+       CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+       CX23885_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum cx23885_stream_port {
+       CX23885_OUTPUT_PORT_MEMORY,
+       CX23885_OUTPUT_PORT_STREAMING,
+       CX23885_OUTPUT_PORT_SERIAL
+};
+enum cx23885_data_xfer_status {
+       CX23885_MORE_BUFFERS_FOLLOW,
+       CX23885_LAST_BUFFER,
+};
+enum cx23885_picture_mask {
+       CX23885_PICTURE_MASK_NONE,
+       CX23885_PICTURE_MASK_I_FRAMES,
+       CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
+       CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum cx23885_vbi_mode_bits {
+       CX23885_VBI_BITS_SLICED,
+       CX23885_VBI_BITS_RAW,
+};
+enum cx23885_vbi_insertion_bits {
+       CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+       CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+       CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum cx23885_dma_unit {
+       CX23885_DMA_BYTES,
+       CX23885_DMA_FRAMES,
+};
+enum cx23885_dma_transfer_status_bits {
+       CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
+       CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
+       CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum cx23885_pause {
+       CX23885_PAUSE_ENCODING,
+       CX23885_RESUME_ENCODING,
+};
+enum cx23885_copyright {
+       CX23885_COPYRIGHT_OFF,
+       CX23885_COPYRIGHT_ON,
+};
+enum cx23885_notification_type {
+       CX23885_NOTIFICATION_REFRESH,
+};
+enum cx23885_notification_status {
+       CX23885_NOTIFICATION_OFF,
+       CX23885_NOTIFICATION_ON,
+};
+enum cx23885_notification_mailbox {
+       CX23885_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum cx23885_field1_lines {
+       CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
+       CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
+       CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum cx23885_field2_lines {
+       CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
+       CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
+       CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum cx23885_custom_data_type {
+       CX23885_CUSTOM_EXTENSION_USR_DATA,
+       CX23885_CUSTOM_PRIVATE_PACKET,
+};
+enum cx23885_mute {
+       CX23885_UNMUTE,
+       CX23885_MUTE,
+};
+enum cx23885_mute_video_mask {
+       CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
+       CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
+       CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum cx23885_mute_video_shift {
+       CX23885_MUTE_VIDEO_V_SHIFT = 8,
+       CX23885_MUTE_VIDEO_U_SHIFT = 16,
+       CX23885_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* defines below are from ivtv-driver.h */
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+/* Registers */
+/* IVTV_REG_OFFSET */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
+#define IVTV_REG_SPU (0x9050)
+#define IVTV_REG_HW_BLOCKS (0x9054)
+#define IVTV_REG_VPU (0x9058)
+#define IVTV_REG_APU (0xA064)
+
+/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
+  bits 31-16
++-----------+
+| Reserved  |
++-----------+
+  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
++-------+-------+-------+-------+-------+-------+-------+-------+
+| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+#define MC417_MIWR     0x8000
+#define MC417_MIRD     0x4000
+#define MC417_MICS     0x2000
+#define MC417_MIRDY    0x1000
+#define MC417_MIADDR   0x0F00
+#define MC417_MIDATA   0x00FF
+
+/* MIADDR* nibble definitions */
+#define  MCI_MEMORY_DATA_BYTE0          0x000
+#define  MCI_MEMORY_DATA_BYTE1          0x100
+#define  MCI_MEMORY_DATA_BYTE2          0x200
+#define  MCI_MEMORY_DATA_BYTE3          0x300
+#define  MCI_MEMORY_ADDRESS_BYTE2       0x400
+#define  MCI_MEMORY_ADDRESS_BYTE1       0x500
+#define  MCI_MEMORY_ADDRESS_BYTE0       0x600
+#define  MCI_REGISTER_DATA_BYTE0        0x800
+#define  MCI_REGISTER_DATA_BYTE1        0x900
+#define  MCI_REGISTER_DATA_BYTE2        0xA00
+#define  MCI_REGISTER_DATA_BYTE3        0xB00
+#define  MCI_REGISTER_ADDRESS_BYTE0     0xC00
+#define  MCI_REGISTER_ADDRESS_BYTE1     0xD00
+#define  MCI_REGISTER_MODE              0xE00
+
+/* Read and write modes */
+#define  MCI_MODE_REGISTER_READ         0
+#define  MCI_MODE_REGISTER_WRITE        1
+#define  MCI_MODE_MEMORY_READ           0
+#define  MCI_MODE_MEMORY_WRITE          0x40
+
+/*** Bit definitions for MC417_CTL register ****
+ bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
++--------+-------------+--------+--------------+------------+
+|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
++--------+-------------+--------+--------------+------------+
+***/
+#define MC417_SPD_CTL(x)       (((x) << 4) & 0x00000030)
+#define MC417_GPIO_SEL(x)      (((x) << 1) & 0x00000006)
+#define MC417_UART_GPIO_EN     0x00000001
+
+/* Values for speed control */
+#define MC417_SPD_CTL_SLOW     0x1
+#define MC417_SPD_CTL_MEDIUM   0x0
+#define MC417_SPD_CTL_FAST     0x3     /* b'1x, but we use b'11 */
+
+/* Values for GPIO select */
+#define MC417_GPIO_SEL_GPIO3   0x3
+#define MC417_GPIO_SEL_GPIO2   0x2
+#define MC417_GPIO_SEL_GPIO1   0x1
+#define MC417_GPIO_SEL_GPIO0   0x0
+
+void cx23885_mc417_init(struct cx23885_dev *dev)
+{
+       u32 regval;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Configure MC417_CTL register to defaults. */
+       regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST)      |
+                MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3)   |
+                MC417_UART_GPIO_EN;
+       cx_write(MC417_CTL, regval);
+
+       /* Configure MC417_OEN to defaults. */
+       regval = MC417_MIRDY;
+       cx_write(MC417_OEN, regval);
+
+       /* Configure MC417_RWD to defaults. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
+       cx_write(MC417_RWD, regval);
+}
+
+static int mc417_wait_ready(struct cx23885_dev *dev)
+{
+       u32 mi_ready;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+       for (;;) {
+               mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
+               if (mi_ready != 0)
+                       return 0;
+               if (time_after(jiffies, timeout))
+                       return -1;
+               udelay(1);
+       }
+}
+
+static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
+{
+       u32 regval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
+               (value & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+
+       /* Transition CS/WR to effect write transaction across bus. */
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
+               ((value >> 8) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
+               ((value >> 16) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
+               ((value >> 24) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Indicate that this is a write. */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+               MCI_MODE_REGISTER_WRITE;
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       return mc417_wait_ready(dev);
+}
+
+static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
+{
+       int retval;
+       u32 regval;
+       u32 tempval;
+       u32 dataval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+               ((address & 0x00FF));
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Indicate that this is a register read. */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+               MCI_MODE_REGISTER_READ;
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       retval = mc417_wait_ready(dev);
+
+       /* switch the DAT0-7 GPIO[10:3] to input mode */
+       cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+       /* Read data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+
+       /* Transition RD to effect read transaction across bus.
+        * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+        * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
+        * input only...)
+        */
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+
+       /* Collect byte */
+       tempval = cx_read(MC417_RWD);
+       dataval = tempval & 0x000000FF;
+
+       /* Bring CS and RD high. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 8);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 16);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 24);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       *value  = dataval;
+
+       return retval;
+}
+
+int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
+{
+       u32 regval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
+               (value & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+
+       /* Transition CS/WR to effect write transaction across bus. */
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
+               ((value >> 8) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
+               ((value >> 16) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
+               ((value >> 24) & 0x000000FF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+               MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       return mc417_wait_ready(dev);
+}
+
+int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
+{
+       int retval;
+       u32 regval;
+       u32 tempval;
+       u32 dataval;
+
+       /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+        * which is an input.
+        */
+       cx_write(MC417_OEN, MC417_MIRDY);
+
+       /* Write address byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+               MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+               ((address >> 8) & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Write address byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+               (address & 0xFF);
+       cx_write(MC417_RWD, regval);
+       regval |= MC417_MICS | MC417_MIWR;
+       cx_write(MC417_RWD, regval);
+
+       /* Wait for the trans to complete (MC417_MIRDY asserted). */
+       retval = mc417_wait_ready(dev);
+
+       /* switch the DAT0-7 GPIO[10:3] to input mode */
+       cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+       /* Read data byte 3 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+
+       /* Transition RD to effect read transaction across bus. */
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+       cx_write(MC417_RWD, regval);
+
+       /* Collect byte */
+       tempval = cx_read(MC417_RWD);
+       dataval = ((tempval & 0x000000FF) << 24);
+
+       /* Bring CS and RD high. */
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 2 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 16);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 1 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= ((tempval & 0x000000FF) << 8);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       /* Read data byte 0 */
+       regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+       regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+       cx_write(MC417_RWD, regval);
+       tempval = cx_read(MC417_RWD);
+       dataval |= (tempval & 0x000000FF);
+       regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+       cx_write(MC417_RWD, regval);
+
+       *value  = dataval;
+
+       return retval;
+}
+
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+char *cmd_to_str(int cmd)
+{
+       switch (cmd) {
+       case CX2341X_ENC_PING_FW:
+               return  "PING_FW";
+       case CX2341X_ENC_START_CAPTURE:
+               return  "START_CAPTURE";
+       case CX2341X_ENC_STOP_CAPTURE:
+               return  "STOP_CAPTURE";
+       case CX2341X_ENC_SET_AUDIO_ID:
+               return  "SET_AUDIO_ID";
+       case CX2341X_ENC_SET_VIDEO_ID:
+               return  "SET_VIDEO_ID";
+       case CX2341X_ENC_SET_PCR_ID:
+               return  "SET_PCR_PID";
+       case CX2341X_ENC_SET_FRAME_RATE:
+               return  "SET_FRAME_RATE";
+       case CX2341X_ENC_SET_FRAME_SIZE:
+               return  "SET_FRAME_SIZE";
+       case CX2341X_ENC_SET_BIT_RATE:
+               return  "SET_BIT_RATE";
+       case CX2341X_ENC_SET_GOP_PROPERTIES:
+               return  "SET_GOP_PROPERTIES";
+       case CX2341X_ENC_SET_ASPECT_RATIO:
+               return  "SET_ASPECT_RATIO";
+       case CX2341X_ENC_SET_DNR_FILTER_MODE:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_CORING_LEVELS:
+               return  "SET_CORING_LEVELS";
+       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+               return  "SET_SPATIAL_FILTER_TYPE";
+       case CX2341X_ENC_SET_VBI_LINE:
+               return  "SET_VBI_LINE";
+       case CX2341X_ENC_SET_STREAM_TYPE:
+               return  "SET_STREAM_TYPE";
+       case CX2341X_ENC_SET_OUTPUT_PORT:
+               return  "SET_OUTPUT_PORT";
+       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+               return  "SET_AUDIO_PROPERTIES";
+       case CX2341X_ENC_HALT_FW:
+               return  "HALT_FW";
+       case CX2341X_ENC_GET_VERSION:
+               return  "GET_VERSION";
+       case CX2341X_ENC_SET_GOP_CLOSURE:
+               return  "SET_GOP_CLOSURE";
+       case CX2341X_ENC_GET_SEQ_END:
+               return  "GET_SEQ_END";
+       case CX2341X_ENC_SET_PGM_INDEX_INFO:
+               return  "SET_PGM_INDEX_INFO";
+       case CX2341X_ENC_SET_VBI_CONFIG:
+               return  "SET_VBI_CONFIG";
+       case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
+               return  "SET_DMA_BLOCK_SIZE";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
+               return  "GET_PREV_DMA_INFO_MB_10";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
+               return  "GET_PREV_DMA_INFO_MB_9";
+       case CX2341X_ENC_SCHED_DMA_TO_HOST:
+               return  "SCHED_DMA_TO_HOST";
+       case CX2341X_ENC_INITIALIZE_INPUT:
+               return  "INITIALIZE_INPUT";
+       case CX2341X_ENC_SET_FRAME_DROP_RATE:
+               return  "SET_FRAME_DROP_RATE";
+       case CX2341X_ENC_PAUSE_ENCODER:
+               return  "PAUSE_ENCODER";
+       case CX2341X_ENC_REFRESH_INPUT:
+               return  "REFRESH_INPUT";
+       case CX2341X_ENC_SET_COPYRIGHT:
+               return  "SET_COPYRIGHT";
+       case CX2341X_ENC_SET_EVENT_NOTIFICATION:
+               return  "SET_EVENT_NOTIFICATION";
+       case CX2341X_ENC_SET_NUM_VSYNC_LINES:
+               return  "SET_NUM_VSYNC_LINES";
+       case CX2341X_ENC_SET_PLACEHOLDER:
+               return  "SET_PLACEHOLDER";
+       case CX2341X_ENC_MUTE_VIDEO:
+               return  "MUTE_VIDEO";
+       case CX2341X_ENC_MUTE_AUDIO:
+               return  "MUTE_AUDIO";
+       case CX2341X_ENC_MISC:
+               return  "MISC";
+       default:
+               return "UNKNOWN";
+       }
+}
+
+static int cx23885_mbox_func(void *priv,
+                            u32 command,
+                            int in,
+                            int out,
+                            u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx23885_dev *dev = priv;
+       unsigned long timeout;
+       u32 value, flag, retval = 0;
+       int i;
+
+       dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
+               cmd_to_str(command));
+
+       /* this may not be 100% safe if we can't read any memory location
+          without side effects */
+       mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
+       if (value != 0x12345678) {
+               printk(KERN_ERR
+                       "Firmware and/or mailbox pointer not initialized "
+                       "or corrupted, signature = 0x%x, cmd = %s\n", value,
+                       cmd_to_str(command));
+               return -1;
+       }
+
+       /* This read looks at 32 bits, but flag is only 8 bits.
+        * Seems we also bail if CMD or TIMEOUT bytes are set???
+        */
+       mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+       if (flag) {
+               printk(KERN_ERR "ERROR: Mailbox appears to be in use "
+                       "(%x), cmd = %s\n", flag, cmd_to_str(command));
+               return -1;
+       }
+
+       flag |= 1; /* tell 'em we're working on it */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* write command + args + fill remaining with zeros */
+       /* command code */
+       mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
+       mc417_memory_write(dev, dev->cx23417_mailbox + 3,
+               IVTV_API_STD_TIMEOUT); /* timeout */
+       for (i = 0; i < in; i++) {
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
+               dprintk(3, "API Input %d = %d\n", i, data[i]);
+       }
+       for (; i < CX2341X_MBOX_MAX_DATA; i++)
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
+
+       flag |= 3; /* tell 'em we're done writing */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* wait for firmware to handle the API command */
+       timeout = jiffies + msecs_to_jiffies(10);
+       for (;;) {
+               mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+               if (0 != (flag & 4))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "ERROR: API Mailbox timeout\n");
+                       return -1;
+               }
+               udelay(10);
+       }
+
+       /* read output values */
+       for (i = 0; i < out; i++) {
+               mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
+               dprintk(3, "API Output %d = %d\n", i, data[i]);
+       }
+
+       mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
+       dprintk(3, "API result = %d\n", retval);
+
+       flag = 0;
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       return retval;
+}
+
+/* We don't need to call the API often, so using just one
+ * mailbox will probably suffice
+ */
+static int cx23885_api_cmd(struct cx23885_dev *dev,
+                          u32 command,
+                          u32 inputcnt,
+                          u32 outputcnt,
+                          ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i, err;
+
+       dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
+
+       va_start(vargs, outputcnt);
+       for (i = 0; i < inputcnt; i++)
+               data[i] = va_arg(vargs, int);
+
+       err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
+       for (i = 0; i < outputcnt; i++) {
+               int *vptr = va_arg(vargs, int *);
+               *vptr = data[i];
+       }
+       va_end(vargs);
+
+       return err;
+}
+
+static int cx23885_find_mailbox(struct cx23885_dev *dev)
+{
+       u32 signature[4] = {
+               0x12345678, 0x34567812, 0x56781234, 0x78123456
+       };
+       int signaturecnt = 0;
+       u32 value;
+       int i;
+
+       dprintk(2, "%s()\n", __func__);
+
+       for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
+               mc417_memory_read(dev, i, &value);
+               if (value == signature[signaturecnt])
+                       signaturecnt++;
+               else
+                       signaturecnt = 0;
+               if (4 == signaturecnt) {
+                       dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
+                       return i+1;
+               }
+       }
+       printk(KERN_ERR "Mailbox signature values not found!\n");
+       return -1;
+}
+
+static int cx23885_load_firmware(struct cx23885_dev *dev)
+{
+       static const unsigned char magic[8] = {
+               0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+       };
+       const struct firmware *firmware;
+       int i, retval = 0;
+       u32 value = 0;
+       u32 gpio_output = 0;
+       u32 checksum = 0;
+       u32 *dataptr;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Save GPIO settings before reset of APU */
+       retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
+       retval |= mc417_memory_read(dev, 0x900C, &value);
+
+       retval  = mc417_register_write(dev,
+               IVTV_REG_VPU, 0xFFFFFFED);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_APU, 0);
+
+       if (retval != 0) {
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+               return -1;
+       }
+
+       retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
+                                 &dev->pci->dev);
+
+       if (retval != 0) {
+               printk(KERN_ERR
+                       "ERROR: Hotplug firmware request failed (%s).\n",
+                       CX2341X_FIRM_ENC_FILENAME);
+               printk(KERN_ERR "Please fix your hotplug setup, the board will "
+                       "not work without firmware loaded!\n");
+               return -1;
+       }
+
+       if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
+               printk(KERN_ERR "ERROR: Firmware size mismatch "
+                       "(have %zd, expected %d)\n",
+                       firmware->size, CX23885_FIRM_IMAGE_SIZE);
+               release_firmware(firmware);
+               return -1;
+       }
+
+       if (0 != memcmp(firmware->data, magic, 8)) {
+               printk(KERN_ERR
+                       "ERROR: Firmware magic mismatch, wrong file?\n");
+               release_firmware(firmware);
+               return -1;
+       }
+
+       /* transfer to the chip */
+       dprintk(2, "Loading firmware ...\n");
+       dataptr = (u32 *)firmware->data;
+       for (i = 0; i < (firmware->size >> 2); i++) {
+               value = *dataptr;
+               checksum += ~value;
+               if (mc417_memory_write(dev, i, value) != 0) {
+                       printk(KERN_ERR "ERROR: Loading firmware failed!\n");
+                       release_firmware(firmware);
+                       return -1;
+               }
+               dataptr++;
+       }
+
+       /* read back to verify with the checksum */
+       dprintk(1, "Verifying firmware ...\n");
+       for (i--; i >= 0; i--) {
+               if (mc417_memory_read(dev, i, &value) != 0) {
+                       printk(KERN_ERR "ERROR: Reading firmware failed!\n");
+                       release_firmware(firmware);
+                       return -1;
+               }
+               checksum -= ~value;
+       }
+       if (checksum) {
+               printk(KERN_ERR
+                       "ERROR: Firmware load failed (checksum mismatch).\n");
+               release_firmware(firmware);
+               return -1;
+       }
+       release_firmware(firmware);
+       dprintk(1, "Firmware upload successful.\n");
+
+       retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
+               IVTV_CMD_HW_BLOCKS_RST);
+
+       /* Restore GPIO settings, make sure EIO14 is enabled as an output. */
+       dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n",
+               __func__, gpio_output);
+       /* Power-up seems to have GPIOs AFU. This was causing digital side
+        * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at
+        * power-up.
+        * gpio_output |= (1<<14);
+        */
+       /* Note: GPIO14 is specific to the HVR1800 here */
+       gpio_output = 0x10ff0411 | (1<<14);
+       retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14));
+       dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n",
+               __func__, gpio_output);
+
+       dprintk(1, "%s: GPIO value  EIO 0-15 was = 0x%x\n",
+               __func__, value);
+       value |= (1<<14);
+       dprintk(1, "%s: GPIO value  EIO 0-15 now = 0x%x\n",
+               __func__, value);
+       retval |= mc417_register_write(dev, 0x900C, value);
+
+       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+       if (retval < 0)
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+       return 0;
+}
+
+void cx23885_417_check_encoder(struct cx23885_dev *dev)
+{
+       u32 status, seq;
+
+       status = seq = 0;
+       cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
+       dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
+}
+
+static void cx23885_codec_settings(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       /* assign frame size */
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->ts1.height, dev->ts1.width);
+
+       dev->mpeg_params.width = dev->ts1.width;
+       dev->mpeg_params.height = dev->ts1.height;
+       dev->mpeg_params.is_50hz =
+               (dev->encodernorm.id & V4L2_STD_625_50) != 0;
+
+       cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
+
+       cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
+       cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
+}
+
+static int cx23885_initialize_codec(struct cx23885_dev *dev)
+{
+       int version;
+       int retval;
+       u32 i, data[7];
+
+       dprintk(1, "%s()\n", __func__);
+
+       retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+       if (retval < 0) {
+               dprintk(2, "%s() PING OK\n", __func__);
+               retval = cx23885_load_firmware(dev);
+               if (retval < 0) {
+                       printk(KERN_ERR "%s() f/w load failed\n", __func__);
+                       return retval;
+               }
+               dev->cx23417_mailbox = cx23885_find_mailbox(dev);
+               if (dev->cx23417_mailbox < 0) {
+                       printk(KERN_ERR "%s() mailbox < 0, error\n",
+                               __func__);
+                       return -1;
+               }
+               retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
+               if (retval < 0) {
+                       printk(KERN_ERR
+                               "ERROR: cx23417 firmware ping failed!\n");
+                       return -1;
+               }
+               retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
+                       &version);
+               if (retval < 0) {
+                       printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
+                               "version failed!\n");
+                       return -1;
+               }
+               dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
+               msleep(200);
+       }
+
+       cx23885_codec_settings(dev);
+       msleep(60);
+
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+               CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+               CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0);
+
+       /* Setup to capture VBI */
+       data[0] = 0x0001BD00;
+       data[1] = 1;          /* frames per interrupt */
+       data[2] = 4;          /* total bufs */
+       data[3] = 0x91559155; /* start codes */
+       data[4] = 0x206080C0; /* stop codes */
+       data[5] = 6;          /* lines */
+       data[6] = 64;         /* BPL */
+
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
+               data[2], data[3], data[4], data[5], data[6]);
+
+       for (i = 2; i <= 24; i++) {
+               int valid;
+
+               valid = ((i >= 19) && (i <= 21));
+               cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
+                               valid, 0 , 0, 0);
+               cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
+                               i | 0x80000000, valid, 0, 0, 0);
+       }
+
+       cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
+       msleep(60);
+
+       /* initialize the video input */
+       cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+       msleep(60);
+
+       /* Enable VIP style pixel invalidation so we work with scaled mode */
+       mc417_memory_write(dev, 2120, 0x00000080);
+
+       /* start capturing to the host interface */
+       cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+               CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+       msleep(10);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+       unsigned int *count, unsigned int *size)
+{
+       struct cx23885_fh *fh = q->priv_data;
+
+       fh->dev->ts1.ts_packet_size  = mpeglinesize;
+       fh->dev->ts1.ts_packet_count = mpeglines;
+
+       *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+       *count = mpegbufs;
+
+       return 0;
+}
+
+static int bb_buf_prepare(struct videobuf_queue *q,
+       struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct cx23885_fh *fh = q->priv_data;
+       return cx23885_buf_prepare(q, &fh->dev->ts1,
+               (struct cx23885_buffer *)vb,
+               field);
+}
+
+static void bb_buf_queue(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx23885_fh *fh = q->priv_data;
+       cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
+}
+
+static void bb_buf_release(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static struct videobuf_queue_ops cx23885_qops = {
+       .buf_setup    = bb_buf_setup,
+       .buf_prepare  = bb_buf_prepare,
+       .buf_queue    = bb_buf_queue,
+       .buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static const u32 *ctrl_classes[] = {
+       cx2341x_mpeg_ctrls,
+       NULL
+};
+
+static int cx23885_queryctrl(struct cx23885_dev *dev,
+       struct v4l2_queryctrl *qctrl)
+{
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (qctrl->id == 0)
+               return -EINVAL;
+
+       /* MPEG V4L2 controls */
+       if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
+               qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+
+       return 0;
+}
+
+static int cx23885_querymenu(struct cx23885_dev *dev,
+       struct v4l2_querymenu *qmenu)
+{
+       struct v4l2_queryctrl qctrl;
+
+       qctrl.id = qmenu->id;
+       cx23885_queryctrl(dev, &qctrl);
+       return v4l2_ctrl_query_menu(qmenu, &qctrl,
+               cx2341x_ctrl_get_menu(qmenu->id));
+}
+
+int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio,
+       struct cx23885_dev *dev, unsigned int cmd, void *arg,
+       v4l2_kioctl driver_ioctl)
+{
+       int err;
+
+       switch (cmd) {
+       /* ---------- tv norms ---------- */
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *e = arg;
+               unsigned int i;
+
+               i = e->index;
+               if (i >= ARRAY_SIZE(cx23885_tvnorms))
+                       return -EINVAL;
+               err = v4l2_video_std_construct(e,
+                       cx23885_tvnorms[e->index].id,
+                       cx23885_tvnorms[e->index].name);
+               e->index = i;
+               if (err < 0)
+                       return err;
+               return 0;
+       }
+       case VIDIOC_G_STD:
+       {
+               v4l2_std_id *id = arg;
+
+               *id = dev->encodernorm.id;
+               return 0;
+       }
+       case VIDIOC_S_STD:
+       {
+               v4l2_std_id *id = arg;
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
+                       if (*id & cx23885_tvnorms[i].id)
+                               break;
+               if (i == ARRAY_SIZE(cx23885_tvnorms))
+                       return -EINVAL;
+               dev->encodernorm = cx23885_tvnorms[i];
+
+               return 0;
+       }
+
+       /* ------ input switching ---------- */
+       case VIDIOC_ENUMINPUT:
+       {
+               struct cx23885_input *input;
+               struct v4l2_input *i = arg;
+               unsigned int n;
+
+               n = i->index;
+               if (n >= 4)
+                       return -EINVAL;
+               input = &cx23885_boards[dev->board].input[n];
+               if (input->type == 0)
+                       return -EINVAL;
+               memset(i, 0, sizeof(*i));
+               i->index = n;
+               /* FIXME
+                * strcpy(i->name, input->name); */
+               strcpy(i->name, "unset");
+               if (input->type == CX23885_VMUX_TELEVISION ||
+                   input->type == CX23885_VMUX_CABLE)
+                       i->type = V4L2_INPUT_TYPE_TUNER;
+               else
+                       i->type  = V4L2_INPUT_TYPE_CAMERA;
+
+               for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
+                       i->std |= cx23885_tvnorms[n].id;
+               return 0;
+       }
+       case VIDIOC_G_INPUT:
+       {
+               unsigned int *i = arg;
+
+               *i = dev->input;
+               return 0;
+       }
+       case VIDIOC_S_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (*i >= 4)
+                       return -EINVAL;
+
+               return 0;
+       }
+
+       /* --- tuner ioctls ------------------------------------------ */
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               if (0 != t->index)
+                       return -EINVAL;
+               memset(t, 0, sizeof(*t));
+               strcpy(t->name, "Television");
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
+               cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+
+               dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+               return 0;
+       }
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+
+               /* Update the A/V core */
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+
+               return 0;
+       }
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               memset(f, 0, sizeof(*f));
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               f->type = V4L2_TUNER_ANALOG_TV;
+               f->frequency = dev->freq;
+
+               /* Assumption that tuner is always on bus 1 */
+               cx23885_call_i2c_clients(&dev->i2c_bus[1],
+                       VIDIOC_G_FREQUENCY, f);
+
+               return 0;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
+                       dev->tuner_type);
+               dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
+                       f->tuner, f->type);
+               if (UNSET == dev->tuner_type)
+                       return -EINVAL;
+               if (f->tuner != 0)
+                       return -EINVAL;
+               if (f->type != V4L2_TUNER_ANALOG_TV)
+                       return -EINVAL;
+               dev->freq = f->frequency;
+
+               /* Assumption that tuner is always on bus 1 */
+               cx23885_call_i2c_clients(&dev->i2c_bus[1],
+                       VIDIOC_S_FREQUENCY, f);
+               return 0;
+       }
+       case VIDIOC_S_CTRL:
+       {
+               /* Update the A/V core */
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg);
+               return 0;
+       }
+       default:
+               /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl
+                * (driver_ioctl) */
+               return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+                                                 driver_ioctl);
+       }
+
+       return 0;
+}
+
+static int mpeg_do_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, void *arg)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_tsport  *tsport = &dev->ts1;
+
+       if (v4l_debug > 1)
+               v4l_print_ioctl(dev->name, cmd);
+
+       switch (cmd) {
+
+       /* --- capabilities ------------------------------------------ */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memset(cap, 0, sizeof(*cap));
+               strcpy(cap->driver, dev->name);
+               strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+                       sizeof(cap->card));
+               sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+               cap->version = CX23885_VERSION_CODE;
+               cap->capabilities =
+                       V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_READWRITE     |
+                       V4L2_CAP_STREAMING     |
+                       0;
+               if (UNSET != dev->tuner_type)
+                       cap->capabilities |= V4L2_CAP_TUNER;
+
+               return 0;
+       }
+
+       /* --- capture ioctls ---------------------------------------- */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *f = arg;
+               int index;
+
+               index = f->index;
+               if (index != 0)
+                       return -EINVAL;
+
+               memset(f, 0, sizeof(*f));
+               f->index = index;
+               strlcpy(f->description, "MPEG", sizeof(f->description));
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->pixelformat = V4L2_PIX_FMT_MPEG;
+               return 0;
+       }
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               memset(f, 0, sizeof(*f));
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.colorspace   = 0;
+               f->fmt.pix.width        = dev->ts1.width;
+               f->fmt.pix.height       = dev->ts1.height;
+               f->fmt.pix.field        = fh->mpegq.field;
+               dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+                       dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+               return 0;
+       }
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.sizeimage    =
+               f->fmt.pix.colorspace   = 0;
+               dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+                       dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+               return 0;
+       }
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *f = arg;
+
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    =
+                       dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+               f->fmt.pix.colorspace   = 0;
+               dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+                       f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+               return 0;
+       }
+
+       /* --- streaming capture ------------------------------------- */
+       case VIDIOC_REQBUFS:
+               return videobuf_reqbufs(&fh->mpegq, arg);
+
+       case VIDIOC_QUERYBUF:
+               return videobuf_querybuf(&fh->mpegq, arg);
+
+       case VIDIOC_QBUF:
+               return videobuf_qbuf(&fh->mpegq, arg);
+
+       case VIDIOC_DQBUF:
+               return videobuf_dqbuf(&fh->mpegq, arg,
+                                     file->f_flags & O_NONBLOCK);
+
+       case VIDIOC_STREAMON:
+               return videobuf_streamon(&fh->mpegq);
+
+       case VIDIOC_STREAMOFF:
+               return videobuf_streamoff(&fh->mpegq);
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *f = arg;
+
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd);
+       }
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *f = arg;
+               struct cx2341x_mpeg_params p;
+               int err;
+
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               p = dev->mpeg_params;
+               err = cx2341x_ext_ctrls(&p, 0, f, cmd);
+               if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
+                       err = cx2341x_update(dev, cx23885_mbox_func,
+                               &dev->mpeg_params, &p);
+                       dev->mpeg_params = p;
+               }
+               return err;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                       CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+                       CX23885_RAW_BITS_NONE);
+               cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+                       mpeg_do_ioctl);
+               cx23885_initialize_codec(dev);
+
+               return 0;
+       }
+       case VIDIOC_LOG_STATUS:
+       {
+               char name[32 + 2];
+
+               snprintf(name, sizeof(name), "%s/2", dev->name);
+               printk(KERN_INFO
+                       "%s/2: ============  START LOG STATUS  ============\n",
+                      dev->name);
+               cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
+                       NULL);
+               cx2341x_log_status(&dev->mpeg_params, name);
+               printk(KERN_INFO
+                       "%s/2: =============  END LOG STATUS  =============\n",
+                      dev->name);
+               return 0;
+       }
+       case VIDIOC_QUERYMENU:
+               return cx23885_querymenu(dev, arg);
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *c = arg;
+
+               return cx23885_queryctrl(dev, c);
+       }
+
+       default:
+               return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+                               mpeg_do_ioctl);
+       }
+       return 0;
+}
+
+static int mpeg_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+}
+
+static int mpeg_open(struct inode *inode, struct file *file)
+{
+       int minor = iminor(inode);
+       struct cx23885_dev *h, *dev = NULL;
+       struct list_head *list;
+       struct cx23885_fh *fh;
+
+       dprintk(2, "%s()\n", __func__);
+
+       list_for_each(list, &cx23885_devlist) {
+               h = list_entry(list, struct cx23885_dev, devlist);
+               if (h->v4l_device->minor == minor) {
+                       dev = h;
+                       break;
+               }
+       }
+
+       if (dev == NULL)
+               return -ENODEV;
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->dev      = dev;
+
+       videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
+                           &dev->pci->dev, &dev->ts1.slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                           V4L2_FIELD_INTERLACED,
+                           sizeof(struct cx23885_buffer),
+                           fh);
+
+       return 0;
+}
+
+static int mpeg_release(struct inode *inode, struct file *file)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* FIXME: Review this crap */
+       /* Shut device down on last close */
+       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+               if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
+                       /* stop mpeg capture */
+                       cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                               CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+                               CX23885_RAW_BITS_NONE);
+
+                       msleep(500);
+                       cx23885_417_check_encoder(dev);
+
+                       cx23885_cancel_buffers(&fh->dev->ts1);
+               }
+       }
+
+       if (fh->mpegq.streaming)
+               videobuf_streamoff(&fh->mpegq);
+       if (fh->mpegq.reading)
+               videobuf_read_stop(&fh->mpegq);
+
+       videobuf_mmap_free(&fh->mpegq);
+       file->private_data = NULL;
+       kfree(fh);
+
+       return 0;
+}
+
+static ssize_t mpeg_read(struct file *file, char __user *data,
+       size_t count, loff_t *ppos)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
+       /* Start mpeg encoder on first read. */
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
+                       if (cx23885_initialize_codec(dev) < 0)
+                               return -EINVAL;
+               }
+       }
+
+       return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+                                   file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int mpeg_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s\n", __func__);
+
+       return videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static struct file_operations mpeg_fops = {
+       .owner         = THIS_MODULE,
+       .open          = mpeg_open,
+       .release       = mpeg_release,
+       .read          = mpeg_read,
+       .poll          = mpeg_poll,
+       .mmap          = mpeg_mmap,
+       .ioctl         = mpeg_ioctl,
+       .llseek        = no_llseek,
+};
+
+static struct video_device cx23885_mpeg_template = {
+       .name          = "cx23885",
+       .type          = VID_TYPE_CAPTURE |
+                               VID_TYPE_TUNER |
+                               VID_TYPE_SCALES |
+                               VID_TYPE_MPEG_ENCODER,
+       .fops          = &mpeg_fops,
+       .minor         = -1,
+};
+
+void cx23885_417_unregister(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       if (dev->v4l_device) {
+               if (-1 != dev->v4l_device->minor)
+                       video_unregister_device(dev->v4l_device);
+               else
+                       video_device_release(dev->v4l_device);
+               dev->v4l_device = NULL;
+       }
+}
+
+static struct video_device *cx23885_video_dev_alloc(
+       struct cx23885_tsport *tsport,
+       struct pci_dev *pci,
+       struct video_device *template,
+       char *type)
+{
+       struct video_device *vfd;
+       struct cx23885_dev *dev = tsport->dev;
+
+       dprintk(1, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->minor   = -1;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+               type, cx23885_boards[tsport->dev->board].name);
+       vfd->dev     = &pci->dev;
+       vfd->release = video_device_release;
+       return vfd;
+}
+
+int cx23885_417_register(struct cx23885_dev *dev)
+{
+       /* FIXME: Port1 hardcoded here */
+       int err = -ENODEV;
+       struct cx23885_tsport *tsport = &dev->ts1;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
+               return err;
+
+       /* Set default TV standard */
+       dev->encodernorm = cx23885_tvnorms[0];
+
+       if (dev->encodernorm.id & V4L2_STD_525_60)
+               tsport->height = 480;
+       else
+               tsport->height = 576;
+
+       tsport->width = 720;
+       cx2341x_fill_defaults(&dev->mpeg_params);
+
+       dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+
+       /* Allocate and initialize V4L video device */
+       dev->v4l_device = cx23885_video_dev_alloc(tsport,
+               dev->pci, &cx23885_mpeg_template, "mpeg");
+       err = video_register_device(dev->v4l_device,
+               VFL_TYPE_GRABBER, -1);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
+               return err;
+       }
+
+       /* Initialize MC417 registers */
+       cx23885_mc417_init(dev);
+
+       printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+              dev->name, dev->v4l_device->minor & 0x1f);
+
+       return 0;
+}
index dfa269838e012d8ceb9d6580d2e39f4e03676171..6ebf58724a0134d27737b015a0acced695252ce0 100644 (file)
@@ -73,6 +73,7 @@ struct cx23885_board cx23885_boards[] = {
        [CX23885_BOARD_HAUPPAUGE_HVR1800] = {
                .name           = "Hauppauge WinTV-HVR1800",
                .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_ENCODER,
                .portc          = CX23885_MPEG_DVB,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .tuner_addr     = 0x42, /* 0x84 >> 1 */
@@ -130,6 +131,18 @@ struct cx23885_board cx23885_boards[] = {
                .name           = "Hauppauge WinTV-HVR1500",
                .portc          = CX23885_MPEG_DVB,
        },
+       [CX23885_BOARD_HAUPPAUGE_HVR1200] = {
+               .name           = "Hauppauge WinTV-HVR1200",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1700] = {
+               .name           = "Hauppauge WinTV-HVR1700",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1400] = {
+               .name           = "Hauppauge WinTV-HVR1400",
+               .portc          = CX23885_MPEG_DVB,
+       },
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -181,6 +194,18 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x0070,
                .subdevice = 0x7717,
                .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x71d1,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8101,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8010,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -235,6 +260,12 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
        case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
        case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
        case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+       case 80019:
+               /* WinTV-HVR1400 (Express Card, Retail, IR,
+                * DVB-T and Basic analog */
+       case 81519:
+               /* WinTV-HVR1700 (PCIe, Retail, No IR, half height,
+                * DVB-T and MPEG2 HW Encoder */
                break;
        default:
                printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
@@ -264,7 +295,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
                }
                else {
                        printk(KERN_ERR
-                               "%s(): Unknow command.\n", __FUNCTION__);
+                               "%s(): Unknow command.\n", __func__);
                        return -EINVAL;
                }
                break;
@@ -306,6 +337,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                /* GPIO-15-18 cx23417 READY, CS, RD, WR */
                /* GPIO-19 IR_RX */
 
+               /* CX23417 GPIO's */
+               /* EIO15 Zilog Reset */
+               /* EIO14 S5H1409/CX24227 Reset */
+
                /* Force the TDA8295A into reset and back */
                cx_set(GP0_IO, 0x00040004);
                mdelay(20);
@@ -314,6 +349,50 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                cx_set(GP0_IO, 0x00040004);
                mdelay(20);
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+               /* GPIO-0 tda10048 demodulator reset */
+               /* GPIO-2 tda18271 tuner reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               /* GPIO-0 TDA10048 demodulator reset */
+               /* GPIO-2 TDA8295A Reset */
+               /* GPIO-3-10 cx23417 data0-7 */
+               /* GPIO-11-14 cx23417 addr0-3 */
+               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+
+               /* The following GPIO's are on the interna AVCore (cx25840) */
+               /* GPIO-19 IR_RX */
+               /* GPIO-20 IR_TX 416/DVBT Select */
+               /* GPIO-21 IIS DAT */
+               /* GPIO-22 IIS WCLK */
+               /* GPIO-23 IIS BCLK */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+               /* GPIO-0  Dibcom7000p demodulator reset */
+               /* GPIO-2  xc3028L tuner reset */
+               /* GPIO-13 LED */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00050000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000005);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00050005);
+               break;
        }
 }
 
@@ -324,6 +403,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
                /* FIXME: Implement me */
                break;
        }
@@ -348,11 +429,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
                if (dev->i2c_bus[0].i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0x80);
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
                if (dev->i2c_bus[0].i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xc0);
                break;
@@ -364,17 +448,45 @@ void cx23885_card_setup(struct cx23885_dev *dev)
                ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
                break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+               /* Defaults for VID B - Analog encoder */
+               /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
+               ts1->gen_ctrl_val    = 0x10e;
+               ts1->ts_clk_en_val   = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val     = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+
+               /* APB_TSVALERR_POL (active low)*/
+               ts1->vld_misc_val    = 0x2000;
+               ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+
+               /* Defaults for VID C */
+               ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
        default:
                ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
                ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
        }
 
+       /* Certain boards support analog, or require the avcore to be
+        * loaded, ensure this happens.
+        */
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               request_module("cx25840");
+               break;
+       }
 }
 
 /* ------------------------------------------------------------------ */
index 7f10b273598fd460101c995d8af958845f8958ac..f24abcd06dea0eb1027630be34ca934daa87d6e8 100644 (file)
@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
 static int cx23885_risc_decode(u32 risc)
 {
        static char *instr[16] = {
-               [ RISC_SYNC    >> 28 ] = "sync",
-               [ RISC_WRITE   >> 28 ] = "write",
-               [ RISC_WRITEC  >> 28 ] = "writec",
-               [ RISC_READ    >> 28 ] = "read",
-               [ RISC_READC   >> 28 ] = "readc",
-               [ RISC_JUMP    >> 28 ] = "jump",
-               [ RISC_SKIP    >> 28 ] = "skip",
-               [ RISC_WRITERM >> 28 ] = "writerm",
-               [ RISC_WRITECM >> 28 ] = "writecm",
-               [ RISC_WRITECR >> 28 ] = "writecr",
+               [RISC_SYNC    >> 28] = "sync",
+               [RISC_WRITE   >> 28] = "write",
+               [RISC_WRITEC  >> 28] = "writec",
+               [RISC_READ    >> 28] = "read",
+               [RISC_READC   >> 28] = "readc",
+               [RISC_JUMP    >> 28] = "jump",
+               [RISC_SKIP    >> 28] = "skip",
+               [RISC_WRITERM >> 28] = "writerm",
+               [RISC_WRITECM >> 28] = "writecm",
+               [RISC_WRITECR >> 28] = "writecr",
        };
        static int incr[16] = {
-               [ RISC_WRITE   >> 28 ] = 3,
-               [ RISC_JUMP    >> 28 ] = 3,
-               [ RISC_SKIP    >> 28 ] = 1,
-               [ RISC_SYNC    >> 28 ] = 1,
-               [ RISC_WRITERM >> 28 ] = 3,
-               [ RISC_WRITECM >> 28 ] = 3,
-               [ RISC_WRITECR >> 28 ] = 4,
+               [RISC_WRITE   >> 28] = 3,
+               [RISC_JUMP    >> 28] = 3,
+               [RISC_SKIP    >> 28] = 1,
+               [RISC_SYNC    >> 28] = 1,
+               [RISC_WRITERM >> 28] = 3,
+               [RISC_WRITECM >> 28] = 3,
+               [RISC_WRITECR >> 28] = 4,
        };
        static char *bits[] = {
                "12",   "13",   "14",   "resync",
@@ -260,7 +260,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
        }
        if (bc != 1)
                printk("%s: %d buffers handled (should be 1)\n",
-                      __FUNCTION__, bc);
+                      __func__, bc);
 }
 
 int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -272,7 +272,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
 
        if (ch->cmds_start == 0)
        {
-               dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,
+               dprintk(1, "%s() Erasing channel [%s]\n", __func__,
                        ch->name);
                cx_write(ch->ptr1_reg, 0);
                cx_write(ch->ptr2_reg, 0);
@@ -280,7 +280,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
                cx_write(ch->cnt1_reg, 0);
                return 0;
        } else {
-               dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,
+               dprintk(1, "%s() Configuring channel [%s]\n", __func__,
                        ch->name);
        }
 
@@ -297,7 +297,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
 
        /* write CDT */
        for (i = 0; i < lines; i++) {
-               dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,
+               dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
                        ch->fifo_start + bpl*i);
                cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
                cx_write(cdt + 16*i +  4, 0);
@@ -449,7 +449,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
 
 static void cx23885_reset(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        cx23885_shutdown(dev);
 
@@ -482,7 +482,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
 
 static int cx23885_pci_quirks(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* The cx23885 bridge has a weird bug which causes NMI to be asserted
         * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
@@ -513,11 +513,13 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 
 static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
 {
-       dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno);
+       dprintk(1, "%s(portno=%d)\n", __func__, portno);
 
        /* Transport bus init dma queue  - Common settings */
        port->dma_ctl_val        = 0x11; /* Enable RISC controller and Fifo */
        port->ts_int_msk_val     = 0x1111; /* TS port bits for RISC */
+       port->vld_misc_val       = 0x0;
+       port->hw_sop_ctrl_val    = (0x47 << 16 | 188 << 4);
 
        spin_lock_init(&port->slock);
        port->dev = dev;
@@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
                port->reg_ts_clk_en      = VID_B_TS_CLK_EN;
                port->reg_src_sel        = VID_B_SRC_SEL;
                port->reg_ts_int_msk     = VID_B_INT_MSK;
-               port->reg_ts_int_stat   = VID_B_INT_STAT;
+               port->reg_ts_int_stat    = VID_B_INT_STAT;
                port->sram_chno          = SRAM_CH03; /* VID_B */
                port->pci_irqmask        = 0x02; /* VID_B bit1 */
                break;
@@ -604,14 +606,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
                break;
        default:
                printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
        }
        if (dev->hwrevision)
                printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
        else
                printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
-                       __FUNCTION__, dev->hwrevision);
+                       __func__, dev->hwrevision);
 }
 
 static int cx23885_dev_setup(struct cx23885_dev *dev)
@@ -644,7 +646,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
                BUG();
 
        dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
-               __FUNCTION__, dev->bridge);
+               __func__, dev->bridge);
 
        /* board config */
        dev->board = UNSET;
@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
        dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
 
-       if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+       if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
+               (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
                cx23885_init_tsport(dev, &dev->ts1, 1);
 
-       if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+       if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
+               (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
                cx23885_init_tsport(dev, &dev->ts2, 2);
 
        if (get_resources(dev) < 0) {
@@ -734,9 +738,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        dev->radio_addr = cx23885_boards[dev->board].radio_addr;
 
        dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
-               __FUNCTION__, dev->tuner_type, dev->tuner_addr);
+               __func__, dev->tuner_type, dev->tuner_addr);
        dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
-               __FUNCTION__, dev->radio_type, dev->radio_addr);
+               __func__, dev->radio_type, dev->radio_addr);
 
        /* init hardware */
        cx23885_reset(dev);
@@ -744,28 +748,43 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        cx23885_i2c_register(&dev->i2c_bus[0]);
        cx23885_i2c_register(&dev->i2c_bus[1]);
        cx23885_i2c_register(&dev->i2c_bus[2]);
-       cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
        cx23885_card_setup(dev);
+       cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
        cx23885_ir_init(dev);
 
        if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
                if (cx23885_video_register(dev) < 0) {
                        printk(KERN_ERR "%s() Failed to register analog "
-                               "video adapters on VID_A\n", __FUNCTION__);
+                               "video adapters on VID_A\n", __func__);
                }
        }
 
        if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
                if (cx23885_dvb_register(&dev->ts1) < 0) {
                        printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
-                              __FUNCTION__);
+                              __func__);
+               }
+       } else
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+               if (cx23885_417_register(dev) < 0) {
+                       printk(KERN_ERR
+                               "%s() Failed to register 417 on VID_B\n",
+                              __func__);
                }
        }
 
        if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
                if (cx23885_dvb_register(&dev->ts2) < 0) {
-                       printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
-                              __FUNCTION__);
+                       printk(KERN_ERR
+                               "%s() Failed to register dvb on VID_C\n",
+                              __func__);
+               }
+       } else
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
+               if (cx23885_417_register(dev) < 0) {
+                       printk(KERN_ERR
+                               "%s() Failed to register 417 on VID_C\n",
+                              __func__);
                }
        }
 
@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
        if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
                cx23885_video_unregister(dev);
 
-       if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
                cx23885_dvb_unregister(&dev->ts1);
 
-       if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_417_unregister(dev);
+
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
                cx23885_dvb_unregister(&dev->ts2);
 
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+               cx23885_417_unregister(dev);
+
        cx23885_i2c_unregister(&dev->i2c_bus[2]);
        cx23885_i2c_unregister(&dev->i2c_bus[1]);
        cx23885_i2c_unregister(&dev->i2c_bus[0]);
@@ -952,7 +977,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
        videobuf_waiton(&buf->vb, 0, 0);
        videobuf_dma_unmap(q, dma);
        videobuf_dma_free(dma);
-       btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -960,50 +985,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
 {
        struct cx23885_dev *dev = port->dev;
 
-       dprintk(1, "%s() Register Dump\n", __FUNCTION__);
-       dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() Register Dump\n", __func__);
+       dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __func__,
                cx_read(DEV_CNTRL2));
-       dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __func__,
                cx_read(PCI_INT_MSK));
-       dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __func__,
                cx_read(AUDIO_INT_INT_MSK));
-       dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __func__,
                cx_read(AUD_INT_DMA_CTL));
-       dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __func__,
                cx_read(AUDIO_EXT_INT_MSK));
-       dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __func__,
                cx_read(AUD_EXT_DMA_CTL));
-       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
                cx_read(PAD_CTRL));
-       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
                cx_read(ALT_PIN_OUT_SEL));
-       dprintk(1, "%s() GPIO2                    0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
                cx_read(GPIO2));
-       dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __FUNCTION__,
+       dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __func__,
                port->reg_gpcnt, cx_read(port->reg_gpcnt));
-       dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __func__,
                port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
-       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
                port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
-       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
                port->reg_src_sel, cx_read(port->reg_src_sel));
-       dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
                port->reg_lngth, cx_read(port->reg_lngth));
-       dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
                port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
-       dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __func__,
                port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
-       dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __func__,
                port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
-       dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __func__,
                port->reg_sop_status, cx_read(port->reg_sop_status));
-       dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
                port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
-       dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __func__,
                port->reg_vld_misc, cx_read(port->reg_vld_misc));
-       dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __func__,
                port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
-       dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __FUNCTION__,
+       dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __func__,
                port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
 }
 
@@ -1012,8 +1037,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
                             struct cx23885_buffer   *buf)
 {
        struct cx23885_dev *dev = port->dev;
+       u32 reg;
 
-       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
+       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
                buf->vb.width, buf->vb.height, buf->vb.field);
 
        /* setup fifo + format */
@@ -1031,21 +1057,24 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
                (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
                printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
-                       __FUNCTION__,
+                       __func__,
                        cx23885_boards[dev->board].portb,
                        cx23885_boards[dev->board].portc );
                return -EINVAL;
        }
 
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 0);
+
        udelay(100);
 
        /* If the port supports SRC SELECT, configure it */
        if(port->reg_src_sel)
                cx_write(port->reg_src_sel, port->src_sel_val);
 
-       cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
+       cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
        cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
-       cx_write(port->reg_vld_misc, 0x00);
+       cx_write(port->reg_vld_misc, port->vld_misc_val);
        cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
        udelay(100);
 
@@ -1054,11 +1083,26 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        cx_write(port->reg_gpcnt_ctl, 3);
        q->count = 1;
 
+       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+               reg = cx_read(PAD_CTRL);
+               reg = reg & ~0x1;    /* Clear TS1_OE */
+
+               /* FIXME, bit 2 writing here is questionable */
+               /* set TS1_SOP_OE and TS1_OE_HI */
+               reg = reg | 0xa;
+               cx_write(PAD_CTRL, reg);
+
+               /* FIXME and these two registers should be documented. */
+               cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
+               cx_write(ALT_PIN_OUT_SEL, 0x10100045);
+       }
+
        switch(dev->bridge) {
        case CX23885_BRIDGE_885:
        case CX23885_BRIDGE_887:
                /* enable irqs */
-               dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
+               dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
                cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);
                cx_set(port->reg_dma_ctl, port->dma_ctl_val);
                cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1069,6 +1113,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
 
        cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
 
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 1);
+
        if (debug > 4)
                cx23885_tsport_reg_dump(port);
 
@@ -1078,12 +1125,32 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
 static int cx23885_stop_dma(struct cx23885_tsport *port)
 {
        struct cx23885_dev *dev = port->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       u32 reg;
+
+       dprintk(1, "%s()\n", __func__);
 
        /* Stop interrupts and DMA */
        cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
        cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
 
+       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+               reg = cx_read(PAD_CTRL);
+
+               /* Set TS1_OE */
+               reg = reg | 0x1;
+
+               /* clear TS1_SOP_OE and TS1_OE_HI */
+               reg = reg & ~0xa;
+               cx_write(PAD_CTRL, reg);
+               cx_write(port->reg_src_sel, 0);
+               cx_write(port->reg_gen_ctrl, 8);
+
+       }
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+               cx23885_av_clk(dev, 0);
+
        return 0;
 }
 
@@ -1093,13 +1160,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
        struct cx23885_dev *dev = port->dev;
        struct cx23885_buffer *buf;
 
-       dprintk(5, "%s()\n", __FUNCTION__);
+       dprintk(5, "%s()\n", __func__);
        if (list_empty(&q->active))
        {
                struct cx23885_buffer *prev;
                prev = NULL;
 
-               dprintk(5, "%s() queue is empty\n", __FUNCTION__);
+               dprintk(5, "%s() queue is empty\n", __func__);
 
                for (;;) {
                        if (list_empty(&q->queued))
@@ -1154,7 +1221,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
        int size = port->ts_packet_size * port->ts_packet_count;
        int rc;
 
-       dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+       dprintk(1, "%s: %p\n", __func__, buf);
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
                return -EINVAL;
 
@@ -1197,7 +1264,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
                buf->count    = cx88q->count++;
                mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
                dprintk(1, "[%p/%d] %s - first active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
        } else {
                dprintk( 1, "queue is not empty - append to active\n" );
                prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1208,7 +1275,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
                dprintk( 1, "[%p/%d] %s - append to active\n",
-                        buf, buf->vb.i, __FUNCTION__);
+                        buf, buf->vb.i, __func__);
        }
 }
 
@@ -1239,13 +1306,23 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
        spin_unlock_irqrestore(&port->slock, flags);
 }
 
+void cx23885_cancel_buffers(struct cx23885_tsport *port)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_dmaqueue *q = &port->mpegq;
+
+       dprintk(1, "%s()\n", __FUNCTION__);
+       del_timer_sync(&q->timeout);
+       cx23885_stop_dma(port);
+       do_cancel_buffers(port, "cancel", 0);
+}
 
 static void cx23885_timeout(unsigned long data)
 {
        struct cx23885_tsport *port = (struct cx23885_tsport *)data;
        struct cx23885_dev *dev = port->dev;
 
-       dprintk(1, "%s()\n",__FUNCTION__);
+       dprintk(1, "%s()\n",__func__);
 
        if (debug > 5)
                cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
@@ -1254,16 +1331,77 @@ static void cx23885_timeout(unsigned long data)
        do_cancel_buffers(port, "timeout", 1);
 }
 
+int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
+{
+       /* FIXME: port1 assumption here. */
+       struct cx23885_tsport *port = &dev->ts1;
+       int count = 0;
+       int handled = 0;
+
+       if (status == 0)
+               return handled;
+
+       count = cx_read(port->reg_gpcnt);
+       dprintk(7, "status: 0x%08x  mask: 0x%08x count: 0x%x\n",
+               status, cx_read(port->reg_ts_int_msk), count);
+
+       if ((status & VID_B_MSK_BAD_PKT)         ||
+               (status & VID_B_MSK_OPC_ERR)     ||
+               (status & VID_B_MSK_VBI_OPC_ERR) ||
+               (status & VID_B_MSK_SYNC)        ||
+               (status & VID_B_MSK_VBI_SYNC)    ||
+               (status & VID_B_MSK_OF)          ||
+               (status & VID_B_MSK_VBI_OF)) {
+               printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
+                       "= 0x%x\n", dev->name, status);
+               if (status & VID_B_MSK_BAD_PKT)
+                       dprintk(1, "        VID_B_MSK_BAD_PKT\n");
+               if (status & VID_B_MSK_OPC_ERR)
+                       dprintk(1, "        VID_B_MSK_OPC_ERR\n");
+               if (status & VID_B_MSK_VBI_OPC_ERR)
+                       dprintk(1, "        VID_B_MSK_VBI_OPC_ERR\n");
+               if (status & VID_B_MSK_SYNC)
+                       dprintk(1, "        VID_B_MSK_SYNC\n");
+               if (status & VID_B_MSK_VBI_SYNC)
+                       dprintk(1, "        VID_B_MSK_VBI_SYNC\n");
+               if (status & VID_B_MSK_OF)
+                       dprintk(1, "        VID_B_MSK_OF\n");
+               if (status & VID_B_MSK_VBI_OF)
+                       dprintk(1, "        VID_B_MSK_VBI_OF\n");
+
+               cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
+               cx23885_417_check_encoder(dev);
+       } else if (status & VID_B_MSK_RISCI1) {
+               dprintk(7, "        VID_B_MSK_RISCI1\n");
+               spin_lock(&port->slock);
+               cx23885_wakeup(port, &port->mpegq, count);
+               spin_unlock(&port->slock);
+       } else if (status & VID_B_MSK_RISCI2) {
+               dprintk(7, "        VID_B_MSK_RISCI2\n");
+               spin_lock(&port->slock);
+               cx23885_restart_queue(port, &port->mpegq);
+               spin_unlock(&port->slock);
+       }
+       if (status) {
+               cx_write(port->reg_ts_int_stat, status);
+               handled = 1;
+       }
+
+       return handled;
+}
+
 static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
 {
        struct cx23885_dev *dev = port->dev;
        int handled = 0;
        u32 count;
 
-       if ( (status & VID_BC_MSK_OPC_ERR) ||
-            (status & VID_BC_MSK_BAD_PKT) ||
-            (status & VID_BC_MSK_SYNC) ||
-            (status & VID_BC_MSK_OF))
+       if ((status & VID_BC_MSK_OPC_ERR) ||
+               (status & VID_BC_MSK_BAD_PKT) ||
+               (status & VID_BC_MSK_SYNC) ||
+               (status & VID_BC_MSK_OF))
        {
                if (status & VID_BC_MSK_OPC_ERR)
                        dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
@@ -1277,7 +1415,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
                printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
 
                cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
-               cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
 
        } else if (status & VID_BC_MSK_RISCI1) {
 
@@ -1378,11 +1517,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
        if (ts1_status) {
                if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
                        handled += cx23885_irq_ts(ts1, ts1_status);
+               else
+               if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+                       handled += cx23885_irq_417(dev, ts1_status);
        }
 
        if (ts2_status) {
                if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
                        handled += cx23885_irq_ts(ts2, ts2_status);
+               else
+               if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+                       handled += cx23885_irq_417(dev, ts2_status);
        }
 
        if (vida_status)
@@ -1422,7 +1567,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
        printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
               "latency: %d, mmio: 0x%llx\n", dev->name,
               pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-              dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));
+              dev->pci_lat,
+               (unsigned long long)pci_resource_start(pci_dev, 0));
 
        pci_set_master(pci_dev);
        if (!pci_dma_supported(pci_dev, 0xffffffff)) {
index ed465c007cea64d201b001b20100827c10825608..870d6e197d65152f8c54b1ef0efcf848edbfd6f6 100644 (file)
 #include "tda18271.h"
 #include "lgdt330x.h"
 #include "xc5000.h"
+#include "tda10048.h"
 #include "dvb-pll.h"
 #include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
+#include "tuner-simple.h"
+#include "dib7000p.h"
+#include "dibx000_common.h"
 
 static unsigned int debug;
 
@@ -53,6 +56,8 @@ static unsigned int alt_tuner;
 module_param(alt_tuner, int, 0644);
 MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 /* ------------------------------------------------------------------ */
 
 static int dvb_buf_setup(struct videobuf_queue *q,
@@ -104,6 +109,13 @@ static struct s5h1409_config hauppauge_generic_config = {
        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
 };
 
+static struct tda10048_config hauppauge_hvr1200_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON
+};
+
 static struct s5h1409_config hauppauge_ezqam_config = {
        .demod_address = 0x32 >> 1,
        .output_mode   = S5H1409_SERIAL_OUTPUT,
@@ -164,8 +176,10 @@ static struct tda829x_config tda829x_no_probe = {
 };
 
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 5380, .std_bits = 0x1b },
-       .qam_6    = { .if_freq = 4000, .std_bits = 0x18 },
+       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+                     .if_lvl = 6, .rfagc_top = 0x37 },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+                     .if_lvl = 6, .rfagc_top = 0x37 },
 };
 
 static struct tda18271_config hauppauge_tda18271_config = {
@@ -173,6 +187,96 @@ static struct tda18271_config hauppauge_tda18271_config = {
        .gate    = TDA18271_GATE_ANALOG,
 };
 
+static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+struct dibx000_agc_config xc3028_agc_config = {
+       BAND_VHF | BAND_UHF,    /* band_caps */
+
+       /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+        * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+        * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
+        * P_agc_nb_est=2, P_agc_write=0
+        */
+       (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+               (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+       712,    /* inv_gain */
+       21,     /* time_stabiliz */
+
+       0,      /* alpha_level */
+       118,    /* thlock */
+
+       0,      /* wbd_inv */
+       2867,   /* wbd_ref */
+       0,      /* wbd_sel */
+       2,      /* wbd_alpha */
+
+       0,      /* agc1_max */
+       0,      /* agc1_min */
+       39718,  /* agc2_max */
+       9930,   /* agc2_min */
+       0,      /* agc1_pt1 */
+       0,      /* agc1_pt2 */
+       0,      /* agc1_pt3 */
+       0,      /* agc1_slope1 */
+       0,      /* agc1_slope2 */
+       0,      /* agc2_pt1 */
+       128,    /* agc2_pt2 */
+       29,     /* agc2_slope1 */
+       29,     /* agc2_slope2 */
+
+       17,     /* alpha_mant */
+       27,     /* alpha_exp */
+       23,     /* beta_mant */
+       51,     /* beta_exp */
+
+       1,      /* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.000000
+ * With external clock = 30.000000 */
+struct dibx000_bandwidth_config xc3028_bw_config = {
+       60000,  /* internal */
+       30000,  /* sampling */
+       1,      /* pll_cfg: prediv */
+       8,      /* pll_cfg: ratio */
+       3,      /* pll_cfg: range */
+       1,      /* pll_cfg: reset */
+       0,      /* pll_cfg: bypass */
+       0,      /* misc: refdiv */
+       0,      /* misc: bypclk_div */
+       1,      /* misc: IO_CLK_en_core */
+       1,      /* misc: ADClkSrc */
+       0,      /* misc: modulo */
+       (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+       (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+       20452225, /* timf */
+       30000000  /* xtal_hz */
+};
+
+static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
+       .output_mpeg2_in_188_bytes = 1,
+       .hostbus_diversity = 1,
+       .tuner_is_baseband = 0,
+       .update_lna  = NULL,
+
+       .agc_config_count = 1,
+       .agc = &xc3028_agc_config,
+       .bw  = &xc3028_bw_config,
+
+       .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+       .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+       .pwm_freq_div = 0,
+       .agc_control  = NULL,
+       .spur_protect = 0,
+
+       .output_mode = OUTMODE_MPEG2_SERIAL,
+};
+
 static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
 {
        struct cx23885_tsport *port = ptr;
@@ -182,7 +286,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
        case XC2028_TUNER_RESET:
                /* Send the tuner in then out of reset */
                /* GPIO-2 xc3028 tuner */
-               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
 
                cx_set(GP0_IO, 0x00040000);
                cx_clear(GP0_IO, 0x00000004);
@@ -192,10 +296,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
                msleep(5);
                break;
        case XC2028_RESET_CLK:
-               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
                break;
        default:
-               dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
+               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
                        command, arg);
                return -EINVAL;
        }
@@ -271,8 +375,9 @@ static int dvb_register(struct cx23885_tsport *port)
                                                &fusionhdtv_5_express,
                                                &i2c_bus->i2c_adap);
                if (port->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
-                                  &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, port->dvb.frontend,
+                                  &i2c_bus->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
                }
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -297,13 +402,52 @@ static int dvb_register(struct cx23885_tsport *port)
                        struct xc2028_config cfg = {
                                .i2c_adap  = &i2c_bus->i2c_adap,
                                .i2c_addr  = 0x61,
-                               .video_dev = port,
                                .callback  = cx23885_hvr1500_xc3028_callback,
                        };
                        static struct xc2028_ctrl ctl = {
                                .fname       = "xc3028-v27.fw",
                                .max_len     = 64,
-                               .scode_table = OREN538,
+                               .scode_table = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       port->dvb.frontend, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+               i2c_bus = &dev->i2c_bus[0];
+               port->dvb.frontend = dvb_attach(tda10048_attach,
+                       &hauppauge_hvr1200_config,
+                       &i2c_bus->i2c_adap);
+               if (port->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, port->dvb.frontend,
+                               &dev->i2c_bus[1].i2c_adap, 0x42,
+                               &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, port->dvb.frontend,
+                               0x60, &dev->i2c_bus[1].i2c_adap,
+                               &hauppauge_hvr1200_tuner_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+               i2c_bus = &dev->i2c_bus[0];
+               port->dvb.frontend = dvb_attach(dib7000p_attach,
+                       &i2c_bus->i2c_adap,
+                       0x12, &hauppauge_hvr1400_dib7000_config);
+               if (port->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+                               .i2c_addr  = 0x64,
+                               .callback  = cx23885_hvr1500_xc3028_callback,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname   = "xc3028L-v36.fw",
+                               .max_len = 64,
+                               .demod   = 5000,
+                               .d2633   = 1
                        };
 
                        fe = dvb_attach(xc2028_attach,
@@ -330,7 +474,7 @@ static int dvb_register(struct cx23885_tsport *port)
 
        /* register everything */
        return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
-                                    &dev->pci->dev);
+                                    &dev->pci->dev, adapter_nr);
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -338,7 +482,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
        struct cx23885_dev *dev = port->dev;
        int err;
 
-       dprintk(1, "%s\n", __FUNCTION__);
+       dprintk(1, "%s\n", __func__);
        dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                dev->board,
                dev->name,
@@ -349,12 +493,12 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
 
        /* dvb stuff */
        printk("%s: cx23885 based dvb card\n", dev->name);
-       videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock,
+       videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
                            sizeof(struct cx23885_buffer), port);
        err = dvb_register(port);
        if (err != 0)
-               printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
+               printk("%s() dvb_register failed err = %d\n", __func__, err);
 
        return err;
 }
index 92fe0bd37c84293e9b27e3933d142eaf4c7196ec..c6bb0a05bc1c147fd61527ab3a47bdf790577924 100644 (file)
@@ -33,7 +33,7 @@ static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
@@ -87,10 +87,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
        int retval, cnt;
 
        if (joined_rlen)
-               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
+               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
                        msg->len, joined_rlen);
        else
-               dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
 
        /* Deal with i2c probe functions with zero payload */
        if (msg->len == 0) {
@@ -101,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
                if (!i2c_slave_did_ack(i2c_adap))
                        return -EIO;
 
-               dprintk(1, "%s() returns 0\n", __FUNCTION__);
+               dprintk(1, "%s() returns 0\n", __func__);
                return 0;
        }
 
@@ -176,7 +176,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
 
 
        if (i2c_debug && !joined)
-               dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
 
        /* Deal with i2c probe functions with zero payload */
        if (msg->len == 0) {
@@ -188,7 +188,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
                        return -EIO;
 
 
-               dprintk(1, "%s() returns 0\n", __FUNCTION__);
+               dprintk(1, "%s() returns 0\n", __func__);
                return 0;
        }
 
@@ -238,11 +238,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
        struct cx23885_dev *dev = bus->dev;
        int i, retval = 0;
 
-       dprintk(1, "%s(num = %d)\n", __FUNCTION__, num);
+       dprintk(1, "%s(num = %d)\n", __func__, num);
 
        for (i = 0 ; i < num; i++) {
                dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
-                       __FUNCTION__, num, msgs[i].addr, msgs[i].len);
+                       __func__, num, msgs[i].addr, msgs[i].len);
                if (msgs[i].flags & I2C_M_RD) {
                        /* read */
                        retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
@@ -353,6 +353,8 @@ static struct i2c_client cx23885_i2c_client_template = {
 };
 
 static char *i2c_devs[128] = {
+       [0x10 >> 1]   = "tda10048",
+       [0x12 >> 1]   = "dib7000pc",
        [ 0x1c >> 1 ] = "lgdt3303",
        [ 0x86 >> 1 ] = "tda9887",
        [ 0x32 >> 1 ] = "cx24227",
@@ -360,7 +362,8 @@ static char *i2c_devs[128] = {
        [ 0x84 >> 1 ] = "tda8295",
        [ 0xa0 >> 1 ] = "eeprom",
        [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
-       [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
+       [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
+       [0xc8 >> 1]   = "tuner/xc3028L",
 };
 
 static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -383,7 +386,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
 {
        struct cx23885_dev *dev = bus->dev;
 
-       dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
+       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
 
        memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
               sizeof(bus->i2c_adap));
@@ -420,6 +423,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
        return 0;
 }
 
+void cx23885_av_clk(struct cx23885_dev *dev, int enable)
+{
+       /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+       char buffer[3];
+       struct i2c_msg msg;
+       dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+       /* Register 0x144 */
+       buffer[0] = 0x01;
+       buffer[1] = 0x44;
+       if (enable == 1)
+               buffer[2] = 0x05;
+       else
+               buffer[2] = 0x00;
+
+       msg.addr = 0x44;
+       msg.flags = I2C_M_TEN;
+       msg.len = 3;
+       msg.buf = buffer;
+
+       i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
 /* ----------------------------------------------------------------------- */
 
 /*
index d3c4d2c5cbe05c69c41cc5c685f3bcdb1c3244c2..84652210a28c6fee3d24fbd626de2c4a56d2db97 100644 (file)
@@ -141,7 +141,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
                if (formats[i].fourcc == fourcc)
                        return formats+i;
 
-       printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
+       printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
        return NULL;
 }
 
@@ -292,13 +292,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
        }
        if (bc != 1)
                printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
-                       __FUNCTION__, bc);
+                       __func__, bc);
 }
 
 int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 {
        dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
-               __FUNCTION__,
+               __func__,
                (unsigned int)norm,
                v4l2_norm_to_name(norm));
 
@@ -319,7 +319,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
                                    char *type)
 {
        struct video_device *vfd;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        vfd = video_device_alloc();
        if (NULL == vfd)
@@ -358,7 +358,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query);
 static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
        unsigned int bit)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        if (fh->resources & bit)
                /* have it already allocated */
                return 1;
@@ -392,7 +392,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
        unsigned int bits)
 {
        BUG_ON((fh->resources & bits) != bits);
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        mutex_lock(&dev->lock);
        fh->resources  &= ~bits;
@@ -407,7 +407,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
        memset(&route, 0, sizeof(route));
 
        dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
-               __FUNCTION__,
+               __func__,
                input, INPUT(input)->vmux,
                INPUT(input)->gpio0, INPUT(input)->gpio1,
                INPUT(input)->gpio2, INPUT(input)->gpio3);
@@ -427,7 +427,7 @@ EXPORT_SYMBOL(cx23885_video_mux);
 int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
        unsigned int height, enum v4l2_field field)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return 0;
 }
 
@@ -435,7 +435,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
                           struct cx23885_dmaqueue *q,
                           struct cx23885_buffer *buf)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        /* setup fifo + format */
        cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
@@ -463,7 +463,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev,
 {
        struct cx23885_buffer *buf, *prev;
        struct list_head *item;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (!list_empty(&q->active)) {
                buf = list_entry(q->active.next, struct cx23885_buffer,
@@ -579,13 +579,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                        if (dev->tvnorm & V4L2_STD_NTSC) {
                                /* cx25840 transmits NTSC bottom field first */
                                dprintk(1, "%s() Creating NTSC risc\n",
-                                       __FUNCTION__);
+                                       __func__);
                                line0_offset = buf->bpl;
                                line1_offset = 0;
                        } else {
                                /* All other formats are top field first */
                                dprintk(1, "%s() Creating PAL/SECAM risc\n",
-                                       __FUNCTION__);
+                                       __func__);
                                line0_offset = 0;
                                line1_offset = buf->bpl;
                        }
@@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
-       videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx23885_buffer),
@@ -885,7 +885,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
 
 int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
-       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
+       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
        return 0;
 }
@@ -894,7 +894,7 @@ EXPORT_SYMBOL(cx23885_get_control);
 int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
-               " (disabled - no action)\n", __FUNCTION__);
+               " (disabled - no action)\n", __func__);
        return 0;
 }
 EXPORT_SYMBOL(cx23885_set_control);
@@ -990,7 +990,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
        struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
        int err;
 
-       dprintk(2, "%s()\n", __FUNCTION__);
+       dprintk(2, "%s()\n", __func__);
        err = vidioc_try_fmt_cap(file, priv, f);
 
        if (0 != err)
@@ -999,7 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
        fh->width      = f->fmt.pix.width;
        fh->height     = f->fmt.pix.height;
        fh->vidq.field = f->fmt.pix.field;
-       dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
+       dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
                fh->width, fh->height, fh->vidq.field);
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
        return 0;
@@ -1101,7 +1101,7 @@ static int vidioc_streamon(struct file *file, void *priv,
 {
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev = fh->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
                return -EINVAL;
@@ -1118,7 +1118,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
        struct cx23885_fh *fh = priv;
        struct cx23885_dev *dev = fh->dev;
        int err, res;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
@@ -1136,7 +1136,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        mutex_lock(&dev->lock);
        cx23885_set_tvnorm(dev, *tvnorms);
@@ -1159,7 +1159,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
                [CX23885_VMUX_DEBUG]      = "for debug only",
        };
        unsigned int n;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
 
        n = i->index;
        if (n >= 4)
@@ -1184,7 +1184,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
                                struct v4l2_input *i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        return cx23885_enum_input(dev, i);
 }
 
@@ -1193,7 +1193,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
        *i = dev->input;
-       dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
+       dprintk(1, "%s() returns %d\n", __func__, *i);
        return 0;
 }
 
@@ -1201,10 +1201,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
 
-       dprintk(1, "%s(%d)\n", __FUNCTION__, i);
+       dprintk(1, "%s(%d)\n", __func__, i);
 
        if (i >= 4) {
-               dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
+               dprintk(1, "%s() -EINVAL\n", __func__);
                return -EINVAL;
        }
 
@@ -1389,7 +1389,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
                return handled;
        cx_write(VID_A_INT_STAT, status);
 
-       dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
+       dprintk(2, "%s() status = 0x%08x\n", __func__, status);
        /* risc op code error */
        if (status & (1 << 16)) {
                printk(KERN_WARNING "%s/0: video risc op code error\n",
@@ -1487,7 +1487,7 @@ static const struct file_operations radio_fops = {
 
 void cx23885_video_unregister(struct cx23885_dev *dev)
 {
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        cx_clear(PCI_INT_MSK, 1);
 
        if (dev->video_dev) {
@@ -1505,7 +1505,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
 {
        int err;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        spin_lock_init(&dev->slock);
 
        /* Initialize VBI template */
index 7cb2179f26227456ed25a507ee8ac20a1da3047b..32af87f25e7bbb769a711d1bd6cf125e1bfd3a39 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "btcx-risc.h"
 #include "cx23885-reg.h"
+#include "media/cx2341x.h"
 
 #include <linux/version.h>
 #include <linux/mutex.h>
@@ -59,6 +60,9 @@
 #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP   4
 #define CX23885_BOARD_HAUPPAUGE_HVR1500Q       5
 #define CX23885_BOARD_HAUPPAUGE_HVR1500        6
+#define CX23885_BOARD_HAUPPAUGE_HVR1200        7
+#define CX23885_BOARD_HAUPPAUGE_HVR1700        8
+#define CX23885_BOARD_HAUPPAUGE_HVR1400        9
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -154,6 +158,7 @@ typedef enum {
        CX23885_MPEG_UNDEFINED = 0,
        CX23885_MPEG_DVB,
        CX23885_ANALOG_VIDEO,
+       CX23885_MPEG_ENCODER,
 } port_t;
 
 struct cx23885_board {
@@ -252,6 +257,8 @@ struct cx23885_tsport {
        u32                        gen_ctrl_val;
        u32                        ts_clk_en_val;
        u32                        src_sel_val;
+       u32                        vld_misc_val;
+       u32                        hw_sop_ctrl_val;
 };
 
 struct cx23885_dev {
@@ -312,6 +319,14 @@ struct cx23885_dev {
        struct cx23885_dmaqueue    vidq;
        struct cx23885_dmaqueue    vbiq;
        spinlock_t                 slock;
+
+       /* MPEG Encoder ONLY settings */
+       u32                        cx23417_mailbox;
+       struct cx2341x_mpeg_params mpeg_params;
+       struct video_device        *v4l_device;
+       atomic_t                   v4l_reader_count;
+       struct cx23885_tvnorm      encodernorm;
+
 };
 
 extern struct list_head cx23885_devlist;
@@ -431,6 +446,18 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus);
 extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
 extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
                                     void *arg);
+extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
+
+/* ----------------------------------------------------------- */
+/* cx23885-417.c                                               */
+extern int cx23885_417_register(struct cx23885_dev *dev);
+extern void cx23885_417_unregister(struct cx23885_dev *dev);
+extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
+extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
+extern void cx23885_mc417_init(struct cx23885_dev *dev);
+extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
+extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
+
 
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
index 756a1eeb274e0da969e49a0ad6424e7ea3339035..7fde678b2c4a5fbb0785af63a77cfbee86cb22d2 100644 (file)
@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
 static void input_change(struct i2c_client *client)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
-       v4l2_std_id std = cx25840_get_v4lstd(client);
+       v4l2_std_id std = state->std;
 
        /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
        if (std & V4L2_STD_SECAM) {
@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 
 /* ----------------------------------------------------------------------- */
 
-static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+static int set_v4lstd(struct i2c_client *client)
 {
-       u8 fmt=0;       /* zero is autodetect */
+       struct cx25840_state *state = i2c_get_clientdata(client);
+       u8 fmt = 0;     /* zero is autodetect */
+       u8 pal_m = 0;
 
        /* First tests should be against specific std */
-       if (std == V4L2_STD_NTSC_M_JP) {
-               fmt=0x2;
-       } else if (std == V4L2_STD_NTSC_443) {
-               fmt=0x3;
-       } else if (std == V4L2_STD_PAL_M) {
-               fmt=0x5;
-       } else if (std == V4L2_STD_PAL_N) {
-               fmt=0x6;
-       } else if (std == V4L2_STD_PAL_Nc) {
-               fmt=0x7;
-       } else if (std == V4L2_STD_PAL_60) {
-               fmt=0x8;
+       if (state->std == V4L2_STD_NTSC_M_JP) {
+               fmt = 0x2;
+       } else if (state->std == V4L2_STD_NTSC_443) {
+               fmt = 0x3;
+       } else if (state->std == V4L2_STD_PAL_M) {
+               pal_m = 1;
+               fmt = 0x5;
+       } else if (state->std == V4L2_STD_PAL_N) {
+               fmt = 0x6;
+       } else if (state->std == V4L2_STD_PAL_Nc) {
+               fmt = 0x7;
+       } else if (state->std == V4L2_STD_PAL_60) {
+               fmt = 0x8;
        } else {
                /* Then, test against generic ones */
-               if (std & V4L2_STD_NTSC) {
-                       fmt=0x1;
-               } else if (std & V4L2_STD_PAL) {
-                       fmt=0x4;
-               } else if (std & V4L2_STD_SECAM) {
-                       fmt=0xc;
-               }
+               if (state->std & V4L2_STD_NTSC)
+                       fmt = 0x1;
+               else if (state->std & V4L2_STD_PAL)
+                       fmt = 0x4;
+               else if (state->std & V4L2_STD_SECAM)
+                       fmt = 0xc;
        }
 
        v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
                cx25840_and_or(client, 0x47b, ~6, 0);
        }
        cx25840_and_or(client, 0x400, ~0xf, fmt);
+       cx25840_and_or(client, 0x403, ~0x3, pal_m);
        cx25840_vbi_setup(client);
+       if (!state->is_cx25836)
+               input_change(client);
        return 0;
 }
 
-v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
-{
-       struct cx25840_state *state = i2c_get_clientdata(client);
-       /* check VID_FMT_SEL first */
-       u8 fmt = cx25840_read(client, 0x400) & 0xf;
-
-       if (!fmt) {
-               /* check AFD_FMT_STAT if set to autodetect */
-               fmt = cx25840_read(client, 0x40d) & 0xf;
-       }
-
-       switch (fmt) {
-       case 0x1:
-       {
-               /* if the audio std is A2-M, then this is the South Korean
-                  NTSC standard */
-               if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
-                       return V4L2_STD_NTSC_M_KR;
-               return V4L2_STD_NTSC_M;
-       }
-       case 0x2: return V4L2_STD_NTSC_M_JP;
-       case 0x3: return V4L2_STD_NTSC_443;
-       case 0x4: return V4L2_STD_PAL;
-       case 0x5: return V4L2_STD_PAL_M;
-       case 0x6: return V4L2_STD_PAL_N;
-       case 0x7: return V4L2_STD_PAL_Nc;
-       case 0x8: return V4L2_STD_PAL_60;
-       case 0xc: return V4L2_STD_SECAM;
-       default: return V4L2_STD_UNKNOWN;
-       }
-}
-
 /* ----------------------------------------------------------------------- */
 
 static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 
 static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        struct v4l2_pix_format *pix;
        int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
-       int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+       int is_50Hz = !(state->std & V4L2_STD_525_60);
 
        switch (fmt->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
        }
 
        case VIDIOC_G_STD:
-               *(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
+               *(v4l2_std_id *)arg = state->std;
                break;
 
        case VIDIOC_S_STD:
+               if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
+                       return 0;
                state->radio = 0;
-               return set_v4lstd(client, *(v4l2_std_id *)arg);
+               state->std = *(v4l2_std_id *)arg;
+               return set_v4lstd(client);
 
        case AUDC_SET_RADIO:
                state->radio = 1;
@@ -1291,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client)
        state->id = id;
        state->rev = device_id;
 
+       if (state->is_cx23885) {
+               /* Drive GPIO2 direction and values */
+               cx25840_write(client, 0x160, 0x1d);
+               cx25840_write(client, 0x164, 0x00);
+       }
+
        return 0;
 }
 
index 95093edc9186d669395a0e6b531ba6b186de1fcb..8bf797f48b09d0779d7f7a6423dc0a29954bbf7b 100644 (file)
@@ -38,6 +38,7 @@ struct cx25840_state {
        struct i2c_client *c;
        int pvr150_workaround;
        int radio;
+       v4l2_std_id std;
        enum cx25840_video_input vid_input;
        enum cx25840_audio_input aud_input;
        u32 audclk_freq;
@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
 u8 cx25840_read(struct i2c_client *client, u16 addr);
 u32 cx25840_read4(struct i2c_client *client, u16 addr);
 int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
-v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
 /* cx25850-firmware.c                                                      */
index 1ddf724a2c74ca6332dd52e1f702dfc4bf18aba0..620d295947abd5299ac86337eceb3407e1d3527e 100644 (file)
@@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size)
        return 0;
 }
 
-static int fw_write(struct i2c_client *client, u8 * data, int size)
+static int fw_write(struct i2c_client *client, u8 *data, int size)
 {
-       int sent;
-
-       if ((sent = i2c_master_send(client, data, size)) < size) {
+       if (i2c_master_send(client, data, size) < size) {
                v4l_err(client, "firmware load i2c failure\n");
                return -ENOSYS;
        }
@@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client)
        struct cx25840_state *state = i2c_get_clientdata(client);
        const struct firmware *fw = NULL;
        u8 buffer[4], *ptr;
-       int size, send, retval;
+       int size, retval;
 
        if (state->is_cx23885)
                firmware = FWFILE_CX23885;
@@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client)
        while (size > 0) {
                ptr[0] = 0x08;
                ptr[1] = 0x02;
-               send = size > (FWSEND - 2) ? FWSEND : size + 2;
-               retval = fw_write(client, ptr, send);
+               retval = fw_write(client, ptr, min(FWSEND, size + 2));
 
                if (retval < 0) {
                        release_firmware(fw);
index 6828f59b9d83555dee36e0e7a11656f8a6cfbe92..c754b9d13369f580e1b6a02fd8da07dcdc414e42 100644 (file)
@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
 void cx25840_vbi_setup(struct i2c_client *client)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
-       v4l2_std_id std = cx25840_get_v4lstd(client);
+       v4l2_std_id std = state->std;
        int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
        int luma_lpf,uv_lpf, comb;
        u32 pll_int,pll_frac,pll_post;
@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                        0, 0, V4L2_SLICED_VPS, 0, 0,    /* 9 */
                        0, 0, 0, 0
                };
-               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+               int is_pal = !(state->std & V4L2_STD_525_60);
                int i;
 
                fmt = arg;
@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 
        case VIDIOC_S_FMT:
        {
-               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
+               int is_pal = !(state->std & V4L2_STD_525_60);
                int vbi_offset = is_pal ? 1 : 0;
                int i, x;
                u8 lcr[24];
index 49d3813a9b48e69ac83ac84d8368d94a212fe945..bcf6d9ba063da738dc77f811308467f3a955cff4 100644 (file)
@@ -57,6 +57,7 @@ config VIDEO_CX88_DVB
        select DVB_NXT200X if !DVB_FE_CUSTOMISE
        select DVB_CX24123 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
index 03feb5b49e1b270428cdcb38ae938893324eb0d9..e976fc6bef7ccc7c6ec747fc5594f7a720aff505 100644 (file)
@@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
        BUG_ON(!chip->dma_size);
 
        dprintk(2,"Freeing buffer\n");
-       videobuf_pci_dma_unmap(chip->pci, chip->dma_risc);
+       videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
        videobuf_dma_free(chip->dma_risc);
        btcx_riscmem_free(chip->pci,&chip->buf->risc);
        kfree(chip->buf);
@@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
        BUG_ON(!chip->dma_size);
        BUG_ON(chip->num_periods & (chip->num_periods-1));
 
-       buf = videobuf_pci_alloc(sizeof(*buf));
+       buf = videobuf_sg_alloc(sizeof(*buf));
        if (NULL == buf)
                return -ENOMEM;
 
@@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
        buf->vb.height = chip->num_periods;
        buf->vb.size   = chip->dma_size;
 
-       dma=videobuf_to_dma(&buf->vb);
+       dma = videobuf_to_dma(&buf->vb);
        videobuf_dma_init(dma);
        ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
                        (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
        if (ret < 0)
                goto error;
 
-       ret = videobuf_pci_dma_map(chip->pci,dma);
+       ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
        if (ret < 0)
                goto error;
 
@@ -494,7 +494,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
 
        count = atomic_read(&chip->count);
 
-//     dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
+//     dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
 //             count, new, count & (runtime->periods-1),
 //             runtime->period_size * (count & (runtime->periods-1)));
        return runtime->period_size * (count & (runtime->periods-1));
index a99e9d5950aa0da61483288f4da687f56a427844..61c4f72644b8d2e56ee391915d51409d1922c425 100644 (file)
@@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32;
 module_param(mpegbufs,int,0644);
 MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 
@@ -314,7 +314,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
        u32 value, flag, retval;
        int i;
 
-       dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
+       dprintk(1,"%s: 0x%X\n", __func__, command);
 
        /* this may not be 100% safe if we can't read any memory location
           without side effects */
@@ -693,7 +693,7 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
                return -EINVAL;
 
        /* Standard V4L2 controls */
-       if (cx8800_ctrl_query(qctrl) == 0)
+       if (cx8800_ctrl_query(dev->core, qctrl) == 0)
                return 0;
 
        /* MPEG V4L2 controls */
@@ -933,7 +933,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
        qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
        if (unlikely(qctrl->id == 0))
                return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
+       return cx8800_ctrl_query(dev->core, qctrl);
 }
 
 static int vidioc_enum_input (struct file *file, void *priv,
@@ -1055,7 +1055,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
 
        dev = cx8802_get_device(inode);
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        if (dev == NULL)
                return -ENODEV;
@@ -1065,7 +1065,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        if (drv) {
                err = drv->request_acquire(drv);
                if(err != 0) {
-                       dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+                       dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
                        return err;
                }
        }
@@ -1087,8 +1087,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
        file->private_data = fh;
        fh->dev      = dev;
 
-       videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
@@ -1284,7 +1284,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        struct cx8802_dev *dev = core->dvbdev;
        int err;
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
        dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                core->boardnr,
                core->name,
index 8c9a8adf52de2c2b5af95ed32d0805968857b20f..620159d05506d1c55675ce9ada91c999c14adce0 100644 (file)
@@ -44,6 +44,16 @@ static unsigned int latency = UNSET;
 module_param(latency,int,0444);
 MODULE_PARM_DESC(latency,"pci latency timer");
 
+#define info_printk(core, fmt, arg...) \
+       printk(KERN_INFO "%s: " fmt, core->name , ## arg)
+
+#define warn_printk(core, fmt, arg...) \
+       printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
+
+#define err_printk(core, fmt, arg...) \
+       printk(KERN_ERR "%s: " fmt, core->name , ## arg)
+
+
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
@@ -1354,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = {
                }},
                /* fixme: Add radio support */
                .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xe780,
+               },
        },
        [CX88_BOARD_ADSTECH_PTV_390] = {
                .name           = "ADS Tech Instant Video PCI",
@@ -1401,6 +1415,245 @@ static const struct cx88_board cx88_boards[] = {
                }},
                .mpeg           = CX88_MPEG_DVB,
        },
+       [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
+               .name           = "DViCO FusionHDTV 5 PCI nano",
+               /* xc3008 tuner, digital only for now */
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
+               .name           = "Pinnacle Hybrid PCTV",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
+               .name           = "Winfast TV2000 XP Global",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400, /* pin 2:mute = 0 (off?) */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0800, /* pin 19:audio = 0 (tv) */
+
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400, /* probably?  or 0x0404 to turn mute on */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0808, /* pin 19:audio = 1 (line) */
+
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+       },
+       [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
+               .name           = "PowerColor Real Angel 330",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x00ff,
+                       .gpio1 = 0xf35d,
+                       .gpio3 = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0 = 0x00ff,
+                       .gpio1 = 0xf37d,
+                       .gpio3 = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000ff,
+                       .gpio1  = 0x0f37d,
+                       .gpio3  = 0x00000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x000ff,
+                       .gpio1  = 0x0f35d,
+                       .gpio3  = 0x00000,
+               },
+       },
+       [CX88_BOARD_GENIATECH_X8000_MT] = {
+               /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
+               .name           = "Geniatech X8000-MT DVBT",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e341,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e361,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e361,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x00000000,
+                       .gpio1  = 0x00e3e341,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x00000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
+               .name           = "DViCO FusionHDTV DVB-T PRO",
+               .tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000067df,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000067df,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
+               .name           = "DViCO FusionHDTV 7 Gold",
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x10df,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x16d9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x16d9,
+               }},
+       },
+       [CX88_BOARD_PROLINK_PV_8000GT] = {
+               .name           = "Prolink Pixelview MPEG 8000GT",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x0ff,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio2 = 0x0cfb,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio2 = 0x0cfb,
+               },
+       },
+       /* Both radio, analog and ATSC work with this board.
+          However, for analog to work, s5h1409 gate should be open,
+          otherwise, tuner-xc3028 won't be detected.
+          A proper fix require using the newer i2c methods to add
+          tuner-xc3028 without doing an i2c probe.
+        */
+       [CX88_BOARD_KWORLD_ATSC_120] = {
+               .name           = "Kworld PlusTV HD PCI 120 (ATSC 120)",
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f35d,
+                       .gpio2  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f37e,
+                       .gpio2  = 0x00000000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f37e,
+                       .gpio2  = 0x00000000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x000000ff,
+                       .gpio1  = 0x0000f35d,
+                       .gpio2  = 0x00000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
 };
 
 /* ------------------------------------------------------------------ */
@@ -1605,7 +1858,11 @@ static const struct cx88_subid cx88_subids[] = {
                .subdevice = 0xdb11,
                .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
                /* Re-branded DViCO: UltraView DVB-T Plus */
-       },{
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb30,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
+       }, {
                .subvendor = 0x17de,
                .subdevice = 0x0840,
                .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
@@ -1714,6 +1971,38 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x11bd,
                .subdevice = 0x0051,
                .card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd530,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
+       }, {
+               .subvendor = 0x12ab,
+               .subdevice = 0x1788,
+               .card      = CX88_BOARD_PINNACLE_HYBRID_PCTV,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0xea3d,
+               .card      = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f18,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8852,
+               .card      = CX88_BOARD_GENIATECH_X8000_MT,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd610,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
+       }, {
+               .subvendor = 0x1554,
+               .subdevice = 0x4935,
+               .card      = CX88_BOARD_PROLINK_PV_8000GT,
+       }, {
+               .subvendor = 0x17de,
+               .subdevice = 0x08c1,
+               .card      = CX88_BOARD_KWORLD_ATSC_120,
        },
 };
 
@@ -1731,17 +2020,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
        if (eeprom_data[4] != 0x7d ||
            eeprom_data[5] != 0x10 ||
            eeprom_data[7] != 0x66) {
-               printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n",
-                      core->name);
+               warn_printk(core, "Leadtek eeprom invalid.\n");
                return;
        }
 
        core->board.tuner_type = (eeprom_data[6] == 0x13) ?
                TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
 
-       printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
-              "tuner=%d, eeprom[0]=0x%02x\n",
-              core->name, core->board.tuner_type, eeprom_data[0]);
+       info_printk(core, "Leadtek Winfast 2000XP Expert config: "
+                   "tuner=%d, eeprom[0]=0x%02x\n",
+                   core->board.tuner_type, eeprom_data[0]);
 }
 
 static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -1785,13 +2073,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
                /* known */
                break;
        default:
-               printk("%s: warning: unknown hauppauge model #%d\n",
-                      core->name, tv.model);
+               warn_printk(core, "warning: unknown hauppauge model #%d\n",
+                           tv.model);
                break;
        }
 
-       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-                       core->name, tv.model);
+       info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1837,8 +2124,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
        char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
                ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
 
-       printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name,
-              name ? name : "unknown");
+       info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
        if (NULL == name)
                return;
        core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
@@ -1846,6 +2132,75 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
                CX88_RADIO : 0;
 }
 
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_dvico_xc2028_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               cx_write(MO_GP0_IO, 0x101000);
+               mdelay(5);
+               cx_set(MO_GP0_IO, 0x101010);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* some Geniatech specific stuff                                           */
+
+static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
+                                               int command, int mode)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       break;
+               case CX88_VMUX_DVB:
+                       cx_write(MO_GP1_IO, 0x030302);
+                       mdelay(50);
+                       break;
+               default:
+                       cx_write(MO_GP1_IO, 0x030301);
+                       mdelay(50);
+               }
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(50);
+               cx_write(MO_GP1_IO, 0x101000);
+               mdelay(50);
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(50);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_pv_8000gt_callback(struct cx88_core *core,
+                                  int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               cx_write(MO_GP2_IO, 0xcf7);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xef5);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xcf7);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /* ----------------------------------------------------------------------- */
 /* some DViCO specific stuff                                               */
 
@@ -1874,32 +2229,85 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
                msg.len = (i != 12 ? 5 : 2);
                err = i2c_transfer(&core->i2c_adap, &msg, 1);
                if (err != 1) {
-                       printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err);
+                       warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
+                                         "failed (err = %d)!\n", i, err);
                        return;
                }
        }
 }
 
+static int cx88_xc2028_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       /* Board-specific callbacks */
+       switch (core->boardnr) {
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+       case CX88_BOARD_GENIATECH_X8000_MT:
+       case CX88_BOARD_KWORLD_ATSC_120:
+               return cx88_xc3028_geniatech_tuner_callback(core,
+                                                       command, arg);
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               return cx88_pv_8000gt_callback(core, command, arg);
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               return cx88_dvico_xc2028_callback(core, command, arg);
+       }
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       info_printk(core, "setting GPIO to radio!\n");
+                       cx_write(MO_GP0_IO, 0x4ff);
+                       mdelay(250);
+                       cx_write(MO_GP2_IO, 0xff);
+                       mdelay(250);
+                       break;
+               case CX88_VMUX_DVB:     /* Digital TV*/
+               default:                /* Analog TV */
+                       info_printk(core, "setting GPIO to TV!\n");
+                       break;
+               }
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(250);
+               cx_write(MO_GP1_IO, 0x101000);
+               mdelay(250);
+               cx_write(MO_GP1_IO, 0x101010);
+               mdelay(250);
+               return 0;
+       }
+       return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* Tuner callback function. Currently only needed for the Pinnacle        *
  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both      *
  * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
 
-int cx88_tuner_callback(void *priv, int command, int arg)
+static int cx88_xc5000_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
 {
-       struct i2c_algo_bit_data *i2c_algo = priv;
-       struct cx88_core *core = i2c_algo->data;
-
-       switch(core->boardnr) {
+       switch (core->boardnr) {
        case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               if(command == 0) { /* This is the reset command from xc5000 */
+               if (command == 0) { /* This is the reset command from xc5000 */
                        /* Reset XC5000 tuner via SYS_RSTO_pin */
                        cx_write(MO_SRST_IO, 0);
                        msleep(10);
                        cx_write(MO_SRST_IO, 1);
                        return 0;
+               } else {
+                       err_printk(core, "xc5000: unknown tuner "
+                                  "callback command.\n");
+                       return -EINVAL;
                }
-               else {
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               if (command == 0) { /* This is the reset command from xc5000 */
+                       cx_clear(MO_GP0_IO, 0x00000010);
+                       msleep(10);
+                       cx_set(MO_GP0_IO, 0x00000010);
+                       return 0;
+               } else {
                        printk(KERN_ERR
                                "xc5000: unknown tuner callback command.\n");
                        return -EINVAL;
@@ -1908,6 +2316,36 @@ int cx88_tuner_callback(void *priv, int command, int arg)
        }
        return 0; /* Should never be here */
 }
+
+int cx88_tuner_callback(void *priv, int command, int arg)
+{
+       struct i2c_algo_bit_data *i2c_algo = priv;
+       struct cx88_core *core;
+
+       if (!i2c_algo) {
+               printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
+               return -EINVAL;
+       }
+
+       core = i2c_algo->data;
+
+       if (!core) {
+               printk(KERN_ERR "cx88: Error - device struct undefined.\n");
+               return -EINVAL;
+       }
+
+       switch (core->board.tuner_type) {
+               case TUNER_XC2028:
+                       info_printk(core, "Calling XC2028/3028 callback\n");
+                       return cx88_xc2028_tuner_callback(core, command, arg);
+               case TUNER_XC5000:
+                       info_printk(core, "Calling XC5000 callback\n");
+                       return cx88_xc5000_tuner_callback(core, command, arg);
+       }
+       err_printk(core, "Error: Calling callback for tuner %d\n",
+                  core->board.tuner_type);
+       return -EINVAL;
+}
 EXPORT_SYMBOL(cx88_tuner_callback);
 
 /* ----------------------------------------------------------------------- */
@@ -1918,23 +2356,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
 
        if (0 == pci->subsystem_vendor &&
            0 == pci->subsystem_device) {
-               printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+               printk(KERN_ERR
+                      "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
                       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
                       "%s: workaround that.  Redirect complaints to the vendor of\n"
                       "%s: the TV card.  Best regards,\n"
                       "%s:         -- tux\n",
                       core->name,core->name,core->name,core->name,core->name);
        } else {
-               printk("%s: Your board isn't known (yet) to the driver.  You can\n"
+               printk(KERN_ERR
+                      "%s: Your board isn't known (yet) to the driver.  You can\n"
                       "%s: try to pick one of the existing card configs via\n"
                       "%s: card=<n> insmod option.  Updating to the latest\n"
                       "%s: version might help as well.\n",
                       core->name,core->name,core->name,core->name);
        }
-       printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
-              core->name);
+       err_printk(core, "Here is a list of valid choices for the card=<n> "
+                  "insmod option:\n");
        for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
-               printk("%s:    card=%d -> %s\n",
+               printk(KERN_ERR "%s:    card=%d -> %s\n",
                       core->name, i, cx88_boards[i].name);
 }
 
@@ -1951,9 +2391,57 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
                cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
                udelay(1000);
                break;
+
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               cx_write(MO_GP2_IO, 0xcf7);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xef5);
+               mdelay(50);
+               cx_write(MO_GP2_IO, 0xcf7);
+               msleep(10);
+               break;
+
+        case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               /* Enable the xc5000 tuner */
+               cx_set(MO_GP0_IO, 0x00001010);
+               break;
        }
 }
 
+/*
+ * Sets board-dependent xc3028 configuration
+ */
+void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
+{
+       memset(ctl, 0, sizeof(*ctl));
+
+       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+       ctl->max_len = 64;
+
+       switch (core->boardnr) {
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+               /* Doesn't work with firmware version 2.7 */
+               ctl->fname = "xc3028-v25.fw";
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               ctl->scode_table = XC3028_FE_ZARLINK456;
+               break;
+       case CX88_BOARD_KWORLD_ATSC_120:
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               ctl->demod = XC3028_FE_OREN538;
+               break;
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               /*
+                * This board uses non-MTS firmware
+                */
+               break;
+       default:
+               ctl->demod = XC3028_FE_OREN538;
+               ctl->mts = 1;
+       }
+}
+EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
+
 static void cx88_card_setup(struct cx88_core *core)
 {
        static u8 eeprom[256];
@@ -1991,6 +2479,13 @@ static void cx88_card_setup(struct cx88_core *core)
                cx_write(MO_GP0_IO, 0x000007f8);
                cx_write(MO_GP1_IO, 0x00000001);
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               /* GPIO0:0 is hooked to demod reset */
+               /* GPIO0:4 is hooked to xc3028 reset */
+               cx_write(MO_GP0_IO, 0x00111100);
+               msleep(1);
+               cx_write(MO_GP0_IO, 0x00111111);
+               break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
                /* GPIO0:6 is hooked to FX2 reset pin */
                cx_set(MO_GP0_IO, 0x00004040);
@@ -2038,10 +2533,8 @@ static void cx88_card_setup(struct cx88_core *core)
                        for (i = 0; i < ARRAY_SIZE(buffer); i++)
                                if (2 != i2c_master_send(&core->i2c_client,
                                                        buffer[i],2))
-                                       printk(KERN_WARNING
-                                               "%s: Unable to enable "
-                                               "tuner(%i).\n",
-                                               core->name, i);
+                                       warn_printk(core, "Unable to enable "
+                                                   "tuner(%i).\n", i);
                }
                break;
        case CX88_BOARD_MSI_TVANYWHERE_MASTER:
@@ -2062,6 +2555,22 @@ static void cx88_card_setup(struct cx88_core *core)
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
        }
        }
+
+       if (core->board.tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               /* Fills device-dependent initialization parameters */
+               cx88_setup_xc3028(core, &ctl);
+
+               /* Sends parameters to xc2028/3028 tuner */
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+               info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
+                           ctl.fname);
+               cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
 }
 
 /* ------------------------------------------------------------------ */
@@ -2178,9 +2687,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 
        memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
 
-       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-               core->name,pci->subsystem_vendor,
-               pci->subsystem_device, core->board.name,
+       info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               pci->subsystem_vendor, pci->subsystem_device, core->board.name,
                core->boardnr, card[core->nr] == core->boardnr ?
                "insmod option" : "autodetected");
 
@@ -2189,8 +2697,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
        if (radio[core->nr] != UNSET)
                core->board.radio_type = radio[core->nr];
 
-       printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n",
-              core->name, core->board.tuner_type, core->board.radio_type);
+       info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
+                   core->board.tuner_type, core->board.radio_type);
 
        /* init hardware */
        cx88_reset(core);
@@ -2207,12 +2715,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 
        return core;
 }
-
-/* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
index 01e2ac98970b3d14310bbf52660f85271ef1326b..c4d1aff1fdb4911f186344f59594110a70604c2e 100644 (file)
@@ -47,15 +47,15 @@ MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int nicam = 0;
+static unsigned int nicam;
 module_param(nicam,int,0644);
 MODULE_PARM_DESC(nicam,"tv audio is nicam");
 
-static unsigned int nocomb = 0;
+static unsigned int nocomb;
 module_param(nocomb,int,0644);
 MODULE_PARM_DESC(nocomb,"disable comb filter");
 
@@ -219,7 +219,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
        videobuf_waiton(&buf->vb,0,0);
        videobuf_dma_unmap(q, dma);
        videobuf_dma_free(dma);
-       btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -548,7 +548,7 @@ void cx88_wakeup(struct cx88_core *core,
                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
        }
        if (bc != 1)
-               printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
+               printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
 }
 
 void cx88_shutdown(struct cx88_core *core)
@@ -577,7 +577,7 @@ void cx88_shutdown(struct cx88_core *core)
 
 int cx88_reset(struct cx88_core *core)
 {
-       dprintk(1,"%s\n",__FUNCTION__);
+       dprintk(1,"%s\n",__func__);
        cx88_shutdown(core);
 
        /* clear irq status */
@@ -929,7 +929,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 
        dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
                cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-       cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
+       /* Chroma AGC must be disabled if SECAM is used, we enable it
+          by default on PAL and NTSC */
+       cx_andor(MO_INPUT_FORMAT, 0x40f,
+                norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
 
        // FIXME: as-is from DScaler
        dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
index f7b41eb1bb5a63a689c6e105718f20a262d0a2a0..f1251b844e0823c48128b27fd03b437be611e578 100644 (file)
 #include "nxt200x.h"
 #include "cx24123.h"
 #include "isl6421.h"
+#include "tuner-simple.h"
+#include "tda9887.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(level,fmt, arg...)     if (debug >= level) \
        printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
 
@@ -235,6 +239,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
        .no_tuner      = 1,
 };
 
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+       .demod_address = 0x0f,
+       .if2           = 45600,
+       .no_tuner      = 1,
+};
+
+static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
+       .demod_address = 0x0f,
+       .if2 = 4560,
+       .no_tuner = 1,
+       .demod_init = dvico_fusionhdtv_demod_init,
+};
+
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
        .demod_address = 0x0f,
 };
@@ -266,7 +283,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
-       dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
+       dprintk(1, "%s: index = %d\n", __func__, index);
        if (index == 0)
                cx_clear(MO_GP0_IO, 8);
        else
@@ -357,6 +374,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
        return 0;
 }
 
+static int cx88_pci_nano_callback(void *ptr, int command, int arg)
+{
+       struct cx88_core *core = ptr;
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               /* Send the tuner in then out of reset */
+               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+
+               switch (core->boardnr) {
+               case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+                       /* GPIO-4 xc3028 tuner */
+
+                       cx_set(MO_GP0_IO, 0x00001000);
+                       cx_clear(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       cx_set(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       break;
+               }
+
+               break;
+       case XC2028_RESET_CLK:
+               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
+               break;
+       default:
+               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
+                       command, arg);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct cx24123_config geniatech_dvbs_config = {
        .demod_address = 0x55,
        .set_ts_params = cx24123_set_ts_param,
@@ -383,12 +434,76 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
        .mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
 };
 
+static struct s5h1409_config dvico_hdtv5_pci_nano_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config kworld_atsc_120_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
 static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
        .i2c_address    = 0x64,
        .if_khz         = 5380,
        .tuner_callback = cx88_tuner_callback,
 };
 
+static struct zl10353_config cx88_geniatech_x8000_mt = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+};
+
+static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
+{
+       struct dvb_frontend *fe;
+       struct xc2028_ctrl ctl;
+       struct xc2028_config cfg = {
+               .i2c_adap  = &dev->core->i2c_adap,
+               .i2c_addr  = addr,
+               .ctrl      = &ctl,
+               .callback  = cx88_tuner_callback,
+       };
+
+       if (!dev->dvb.frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc3028\n",
+                      dev->core->name);
+               return -EINVAL;
+       }
+
+       /*
+        * Some xc3028 devices may be hidden by an I2C gate. This is known
+        * to happen with some s5h1409-based devices.
+        * Now that I2C gate is open, sets up xc3028 configuration
+        */
+       cx88_setup_xc3028(dev->core, &ctl);
+
+       fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                      dev->core->name);
+               dvb_frontend_detach(dev->dvb.frontend);
+               dvb_unregister_frontend(dev->dvb.frontend);
+               dev->dvb.frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc3028 attached\n",
+              dev->core->name);
+
+       return 0;
+}
+
 static int dvb_register(struct cx8802_dev *dev)
 {
        /* init struct videobuf_dvb */
@@ -429,8 +544,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &hauppauge_hvr_config,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -497,8 +613,9 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
                                               &dev->vp3054->adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
 #else
                printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
@@ -509,18 +626,36 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &dvico_fusionhdtv_hybrid,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_FE6600);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_FE6600);
                }
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend == NULL)
+                       dev->dvb.frontend = dvb_attach(mt352_attach,
+                                               &dvico_fusionhdtv_mt352_xc3028,
+                                               &dev->core->i2c_adap);
+               /*
+                * On this board, the demod provides the I2C bus pullup.
+                * We must not permit gate_ctrl to be performed, or
+                * the xc3028 cannot communicate on the bus.
+                */
+               if (dev->dvb.frontend)
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
        case CX88_BOARD_PCHDTV_HD3000:
                dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_DTT761X);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_DTT761X);
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
@@ -540,9 +675,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_MICROTUNE_4042);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_MICROTUNE_4042FI5);
                }
                }
                break;
@@ -560,9 +695,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_3_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_THOMSON_DTT761X);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_DTT761X);
                }
                }
                break;
@@ -580,9 +715,11 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &fusionhdtv_5_gold,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
+                       dvb_attach(tda9887_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x43);
                }
                }
                break;
@@ -600,9 +737,11 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &pchdtv_hd5500,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  &dev->core->i2c_adap,
-                                  DVB_PLL_LG_TDVS_H06XF);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
+                       dvb_attach(tda9887_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x43);
                }
                }
                break;
@@ -611,8 +750,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &ati_hdtvwonder,
                                               &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_TUV1236D);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
                }
                break;
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -658,14 +798,62 @@ static int dvb_register(struct cx8802_dev *dev)
                                   &pinnacle_pctv_hd_800i_tuner_config);
                }
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               dev->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &dvico_hdtv5_pci_nano_config,
+                                               &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &dev->core->i2c_adap,
+                               .i2c_addr  = 0x61,
+                               .callback  = cx88_pci_nano_callback,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = "xc3028-v27.fw",
+                               .max_len     = 64,
+                               .scode_table = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       dev->dvb.frontend, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
+               break;
+        case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_geniatech_x8000_mt,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
+        case CX88_BOARD_GENIATECH_X8000_MT:
+               dev->ts_gen_cntrl = 0x00;
+
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_geniatech_x8000_mt,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
+        case CX88_BOARD_KWORLD_ATSC_120:
+               dev->dvb.frontend = dvb_attach(s5h1409_attach,
+                                              &kworld_atsc_120_config,
+                                              &dev->core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       return -EINVAL;
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
                break;
        }
        if (NULL == dev->dvb.frontend) {
-               printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name);
-               return -1;
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      dev->core->name);
+               return -EINVAL;
        }
 
        /* Ensure all frontends negotiate bus access */
@@ -675,7 +863,8 @@ static int dvb_register(struct cx8802_dev *dev)
        cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
        /* register everything */
-       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
+                                    &dev->pci->dev, adapter_nr);
 }
 
 /* ----------------------------------------------------------- */
@@ -685,7 +874,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
 {
        struct cx88_core *core = drv->core;
        int err = 0;
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -708,7 +897,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
 {
        struct cx88_core *core = drv->core;
        int err = 0;
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -726,7 +915,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
        struct cx8802_dev *dev = drv->core->dvbdev;
        int err;
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
        dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
                core->boardnr,
                core->name,
@@ -744,8 +933,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
 
        /* dvb stuff */
        printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
-       videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_TOP,
                            sizeof(struct cx88_buffer),
@@ -764,7 +953,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
        struct cx8802_dev *dev = drv->core->dvbdev;
 
        /* dvb */
-       videobuf_dvb_unregister(&dev->dvb);
+       if (dev->dvb.frontend)
+               videobuf_dvb_unregister(&dev->dvb);
 
        vp3054_i2c_remove(dev);
 
index 566b26af523e74b132113ed968af94782dddc472..c6b44732a082fd743b6fbbc3ac39f4ab511e514f 100644 (file)
 #include "cx88.h"
 #include <media/v4l2-common.h>
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
index bb0911b4d2f683ada952b8197d31c8f7445b667b..53526d997a4e97923231ead7736fa2f9c9c089cf 100644 (file)
@@ -57,7 +57,7 @@ struct cx88_IR {
        u32 mask_keyup;
 };
 
-static int ir_debug = 0;
+static int ir_debug;
 module_param(ir_debug, int, 0644);     /* debug level [IR] */
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
@@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->mask_keyup = 0x80;
                ir->polling = 1; /* ms */
                break;
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               ir_codes = ir_codes_pixelview_new;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0x3f;
+               ir->mask_keyup = 0x80;
+               ir->polling = 1; /* ms */
+               break;
        case CX88_BOARD_KWORLD_LTV883:
                ir_codes = ir_codes_pixelview;
                ir->gpio_addr = MO_GP1_IO;
@@ -310,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir_type = IR_TYPE_RC5;
                ir->sampling = 1;
                break;
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+               ir_codes = ir_codes_powercolor_real_angel;
+               ir->gpio_addr = MO_GP2_IO;
+               ir->mask_keycode = 0x7e;
+               ir->polling = 100; /* ms */
+               break;
        }
 
        if (NULL == ir_codes) {
index e357f415db06601ceab9333994d90aa4d51f4bfa..a6b061c2644a7d72446a0a79713180c64e3d6c8d 100644 (file)
@@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
 
@@ -146,7 +146,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
                udelay(100);
        } else {
-               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
+               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
                        core->board.mpeg );
                return -EINVAL;
        }
@@ -247,7 +247,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
        int rc;
 
-       dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+       dprintk(1, "%s: %p\n", __func__, buf);
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
                return -EINVAL;
 
@@ -289,7 +289,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                buf->count    = cx88q->count++;
                mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
                dprintk(1,"[%p/%d] %s - first active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
 
        } else {
                dprintk( 1, "queue is not empty - append to active\n" );
@@ -299,7 +299,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                buf->count    = cx88q->count++;
                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                dprintk( 1, "[%p/%d] %s - append to active\n",
-                       buf, buf->vb.i, __FUNCTION__);
+                       buf, buf->vb.i, __func__);
        }
 }
 
@@ -342,7 +342,7 @@ static void cx8802_timeout(unsigned long data)
 {
        struct cx8802_dev *dev = (struct cx8802_dev*)data;
 
-       dprintk(1, "%s\n",__FUNCTION__);
+       dprintk(1, "%s\n",__func__);
 
        if (debug)
                cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
            core->active_type_id != drv->type_id)
                return -EBUSY;
 
+       core->input = CX88_VMUX_DVB;
+
        if (drv->advise_acquire)
        {
                mutex_lock(&drv->core->lock);
@@ -623,7 +625,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
                }
                mutex_unlock(&drv->core->lock);
 
-               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
        }
 
        return 0;
@@ -639,7 +641,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
        {
                drv->advise_release(drv);
                core->active_type_id = CX88_BOARD_NONE;
-               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
        }
        mutex_unlock(&drv->core->lock);
 
@@ -813,7 +815,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
 
        dev = pci_get_drvdata(pci_dev);
 
-       dprintk( 1, "%s\n", __FUNCTION__);
+       dprintk( 1, "%s\n", __func__);
 
        if (!list_empty(&dev->drvlist)) {
                struct cx8802_driver *drv, *tmp;
index 76e5c78d8ae44c8698af8611db3fabdf30830fd6..3a1977f41e277ddd681694398ae8de01335cdf5a 100644 (file)
 
 #include "cx88.h"
 
-static unsigned int audio_debug = 0;
+static unsigned int audio_debug;
 module_param(audio_debug, int, 0644);
 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
 
-static unsigned int always_analog = 0;
+static unsigned int always_analog;
 module_param(always_analog,int,0644);
 MODULE_PARM_DESC(always_analog,"force analog audio out");
 
-static unsigned int radio_deemphasis = 0;
+static unsigned int radio_deemphasis;
 module_param(radio_deemphasis,int,0644);
 MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
                 "0=None, 1=50us (elsewhere), 2=75us (USA)");
@@ -265,12 +265,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
        mode |= EN_FMRADIO_EN_RDS;
 
        if (sap) {
-               dprintk("%s SAP (status: unknown)\n", __FUNCTION__);
+               dprintk("%s SAP (status: unknown)\n", __func__);
                set_audio_start(core, SEL_SAP);
                set_audio_registers(core, btsc_sap);
                set_audio_finish(core, mode);
        } else {
-               dprintk("%s (status: known-good)\n", __FUNCTION__);
+               dprintk("%s (status: known-good)\n", __func__);
                set_audio_start(core, SEL_BTSC);
                set_audio_registers(core, btsc);
                set_audio_finish(core, mode);
@@ -351,16 +351,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
        set_audio_start(core,SEL_NICAM);
        switch (core->tvaudio) {
        case WW_L:
-               dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__);
+               dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
                set_audio_registers(core, nicam_l);
                break;
        case WW_I:
-               dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_i);
                break;
        default:
-               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
                set_audio_registers(core, nicam_bgdki_common);
                set_audio_registers(core, nicam_default);
                break;
@@ -600,28 +600,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
        set_audio_start(core, SEL_A2);
        switch (core->tvaudio) {
        case WW_BG:
-               dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
                set_audio_registers(core, a2_bgdk_common);
                set_audio_registers(core, a2_bg);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_DK:
-               dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
                set_audio_registers(core, a2_bgdk_common);
                set_audio_registers(core, a2_dk);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_I:
-               dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__);
+               dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
                set_audio_registers(core, a1_i);
                set_audio_registers(core, a2_deemph50);
                break;
        case WW_L:
-               dprintk("%s AM-L (status: devel)\n", __FUNCTION__);
+               dprintk("%s AM-L (status: devel)\n", __func__);
                set_audio_registers(core, am_l);
                break;
        default:
-               dprintk("%s Warning: wrong value\n", __FUNCTION__);
+               dprintk("%s Warning: wrong value\n", __func__);
                return;
                break;
        };
@@ -637,7 +637,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
 
                { /* end of list */ },
        };
-       dprintk("%s (status: unknown)\n", __FUNCTION__);
+       dprintk("%s (status: unknown)\n", __func__);
 
        set_audio_start(core, SEL_EIAJ);
        set_audio_registers(core, eiaj);
@@ -691,7 +691,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
                { /* end of list */ },
        };
 
-       dprintk("%s (status: unknown)\n", __FUNCTION__);
+       dprintk("%s (status: unknown)\n", __func__);
        set_audio_start(core, SEL_FMRADIO);
 
        switch (deemph) {
index d96ecfcf393a06d0ad99920a9c044d6c71c0ca19..0943060682bcd4ebf6039f32e3288f3d391fa76b 100644 (file)
@@ -11,7 +11,7 @@ static unsigned int vbibufs = 4;
 module_param(vbibufs,int,0644);
 MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
 
-static unsigned int vbi_debug = 0;
+static unsigned int vbi_debug;
 module_param(vbi_debug,int,0644);
 MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
 
index 227179620d13cbe00695e5bbac05efe7a44f51fc..eea23f95edb751d42f9dce1588f817038e0ba5bf 100644 (file)
@@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers");
 MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
 MODULE_PARM_DESC(radio_nr,"radio device numbers");
 
-static unsigned int video_debug = 0;
+static unsigned int video_debug;
 module_param(video_debug,int,0644);
 MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug,int,0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
@@ -228,6 +228,30 @@ static struct cx88_ctrl cx8800_ctls[] = {
                .mask                  = 0x00ff,
                .shift                 = 0,
        },{
+               .v = {
+                       .id            = V4L2_CID_CHROMA_AGC,
+                       .name          = "Chroma AGC",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 10,
+               .shift                 = 10,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_COLOR_KILLER,
+                       .name          = "Color killer",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 9,
+               .shift                 = 9,
+       }, {
        /* --- audio --- */
                .v = {
                        .id            = V4L2_CID_AUDIO_MUTE,
@@ -282,6 +306,8 @@ const u32 cx88_user_ctrls[] = {
        V4L2_CID_AUDIO_VOLUME,
        V4L2_CID_AUDIO_BALANCE,
        V4L2_CID_AUDIO_MUTE,
+       V4L2_CID_CHROMA_AGC,
+       V4L2_CID_COLOR_KILLER,
        0
 };
 EXPORT_SYMBOL(cx88_user_ctrls);
@@ -291,7 +317,7 @@ static const u32 *ctrl_classes[] = {
        NULL
 };
 
-int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
+int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
 {
        int i;
 
@@ -306,6 +332,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
                return 0;
        }
        *qctrl = cx8800_ctls[i].v;
+       /* Report chroma AGC as inactive when SECAM is selected */
+       if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
+           core->tvnorm & V4L2_STD_SECAM)
+               qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+
        return 0;
 }
 EXPORT_SYMBOL(cx8800_ctrl_query);
@@ -776,14 +807,14 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
-       videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
                            fh);
-       videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct cx88_buffer),
@@ -976,6 +1007,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                }
                mask=0xffff;
                break;
+       case V4L2_CID_CHROMA_AGC:
+               /* Do not allow chroma AGC to be enabled for SECAM */
+               value = ((ctl->value - c->off) << c->shift) & c->mask;
+               if (core->tvnorm & V4L2_STD_SECAM && value)
+                       return -EINVAL;
+               break;
        default:
                value = ((ctl->value - c->off) << c->shift) & c->mask;
                break;
@@ -1268,10 +1305,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 static int vidioc_queryctrl (struct file *file, void *priv,
                                struct v4l2_queryctrl *qctrl)
 {
+       struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+
        qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
        if (unlikely(qctrl->id == 0))
                return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
+       return cx8800_ctrl_query(core, qctrl);
 }
 
 static int vidioc_g_ctrl (struct file *file, void *priv,
@@ -1832,8 +1871,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        switch (core->boardnr) {
        case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-               request_module("ir-kbd-i2c");
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
                request_module("rtc-isl1208");
+               /* break intentionally omitted */
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               request_module("ir-kbd-i2c");
        }
 
        /* register v4l devices */
@@ -1917,6 +1959,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
                core->kthread = NULL;
        }
 
+       if (core->ir)
+               cx88_ir_stop(core, core->ir);
+
        cx88_shutdown(core); /* FIXME */
        pci_disable_device(pci_dev);
 
index 37e6d2e4002f54f229f9daff57894462b7ce603c..14ac173f40711e66ca3a2ad51a82dc7c4c222a7d 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "btcx-risc.h"
 #include "cx88-reg.h"
+#include "tuner-xc2028.h"
 
 #include <linux/version.h>
 #include <linux/mutex.h>
@@ -211,6 +212,15 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_HAUPPAUGE_HVR1300       56
 #define CX88_BOARD_ADSTECH_PTV_390         57
 #define CX88_BOARD_PINNACLE_PCTV_HD_800i   58
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
+#define CX88_BOARD_PINNACLE_HYBRID_PCTV    60
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
+#define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
+#define CX88_BOARD_GENIATECH_X8000_MT      63
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
+#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
+#define CX88_BOARD_PROLINK_PV_8000GT       66
+#define CX88_BOARD_KWORLD_ATSC_120         67
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -595,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg);
 extern int cx88_get_resources(const struct cx88_core *core,
                              struct pci_dev *pci);
 extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
+extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
 
 /* ----------------------------------------------------------- */
 /* cx88-tvaudio.c                                              */
@@ -640,7 +651,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
 /* ----------------------------------------------------------- */
 /* cx88-video.c*/
 extern const u32 cx88_user_ctrls[];
-extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
+extern int cx8800_ctrl_query(struct cx88_core *core,
+                            struct v4l2_queryctrl *qctrl);
 int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
 int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
 int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
index d14d803566a3577ff7affaaab0a34e75d13eccb4..cbd92635993d8f1ce7c298f31f79337bb9155681 100644 (file)
@@ -1,5 +1,12 @@
 /*
  * dabdata.h - dab usb firmware and bitstream data
+ *
+ * Copyright (C) 1999 BayCom GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
  */
 
 static INTEL_HEX_RECORD firmware[] = {
index a5731f90be0f842d39aa1a941c50d0ab31d3f6e9..8d1f8ee2a533a48ea3e793b11399873e9d00cd6b 100644 (file)
@@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb)
 /*-------------------------------------------------------------------*/
 static int dabusb_alloc_buffers (pdabusb_t s)
 {
-       int buffers = 0;
+       int transfer_len = 0;
        pbuff_t b;
        unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
        int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
@@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
        dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
                 pipesize, packets, transfer_buffer_length);
 
-       while (buffers < (s->total_buffer_size << 10)) {
+       while (transfer_len < (s->total_buffer_size << 10)) {
                b = kzalloc(sizeof (buff_t), GFP_KERNEL);
                if (!b) {
                        err("kzalloc(sizeof(buff_t))==NULL");
@@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s)
                        b->purb->iso_frame_desc[i].length = pipesize;
                }
 
-               buffers += transfer_buffer_length;
+               transfer_len += transfer_buffer_length;
                list_add_tail (&b->buff_list, &s->free_buff_list);
        }
-       s->got_mem = buffers;
+       s->got_mem = transfer_len;
 
        return 0;
 
index 9ceb6b2f394920af86ff64bc7be36f3a080c3cfb..88d6df71d051a0acc6e2208926e41a0e4a673634 100644 (file)
 
 #define DPC_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
-static int dpc_num = 0;
+static int dpc_num;
 
 #define DPC_INPUTS     2
 static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
index 0f7a0bd86ff4e87a0485f90f162f876a1f2f1202..9caffed2b6b8302637cde0ad128c791cc5ce364e 100644 (file)
@@ -1,11 +1,13 @@
 config VIDEO_EM28XX
-       tristate "Empia EM2800/2820/2840 USB video capture support"
+       tristate "Empia EM28xx USB video capture support"
        depends on VIDEO_DEV && I2C && INPUT
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
+       select VIDEOBUF_VMALLOC
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for Empia 28xx based TV cards.
 
@@ -27,3 +29,13 @@ config VIDEO_EM28XX_ALSA
          To compile this driver as a module, choose M here: the
          module will be called em28xx-alsa
 
+config VIDEO_EM28XX_DVB
+       tristate "DVB/ATSC Support for em28xx based TV cards"
+       depends on VIDEO_EM28XX && DVB_CORE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select VIDEOBUF_DVB
+       select FW_LOADER
+       ---help---
+         This adds support for DVB cards based on the
+         Empiatech em28xx chips.
index 0924550992d0e4f37781bf66b5166ef30ce9a8de..3d1c3cc337fe65c7407d728afab04990bdcd4e98 100644 (file)
@@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o
 
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
 obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
+obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
index 8c67f678266aa83c35104e3f8f80e9e7395d8ebb..92b2a6db4fdc15edea12a61ccbdcfa522da7a534 100644 (file)
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
 #define dprintk(fmt, arg...) do {                                      \
            if (debug)                                                  \
                printk(KERN_INFO "em28xx-audio %s: " fmt,               \
-                                 __FUNCTION__, ##arg);                 \
+                                 __func__, ##arg);             \
        } while (0)
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
index aae7753fef117d1c7b12f0bcc30a83a1f018c19e..50ccf377120488e0d61a40776b4e2a162b529915 100644 (file)
@@ -36,7 +36,6 @@
 #include <media/v4l2-common.h>
 
 #include "em28xx.h"
-#include "tuner-xc2028.h"
 
 static int tuner = -1;
 module_param(tuner, int, 0444);
@@ -52,26 +51,6 @@ struct em28xx_hash_table {
        unsigned int  tuner;
 };
 
-/* Boards supported by driver */
-
-#define EM2800_BOARD_UNKNOWN                   0
-#define EM2820_BOARD_UNKNOWN                   1
-#define EM2820_BOARD_TERRATEC_CINERGY_250      2
-#define EM2820_BOARD_PINNACLE_USB_2            3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
-#define EM2820_BOARD_MSI_VOX_USB_2              5
-#define EM2800_BOARD_TERRATEC_CINERGY_200       6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
-#define EM2800_BOARD_KWORLD_USB2800             8
-#define EM2820_BOARD_PINNACLE_DVC_90           9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
-#define EM2800_BOARD_VGEAR_POCKETTV             15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
-
 struct em28xx_board em28xx_boards[] = {
        [EM2800_BOARD_UNKNOWN] = {
                .name         = "Unknown EM2800 video grabber",
@@ -200,6 +179,7 @@ struct em28xx_board em28xx_boards[] = {
                .tuner_type     = TUNER_XC2028,
                .mts_firmware   = 1,
                .has_12mhz_i2s  = 1,
+               .has_dvb        = 1,
                .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -214,9 +194,6 @@ struct em28xx_board em28xx_boards[] = {
                        .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
-
-               /* gpio's 4, 1, 0 */
-               .analog_gpio = 0x003d2d,
        },
        [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
                .name         = "Terratec Hybrid XS",
@@ -331,7 +308,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Kworld USB2800",
                .is_em2800    = 1,
                .vchannels    = 3,
-               .tuner_type   = TUNER_PHILIPS_ATSC,
+               .tuner_type   = TUNER_PHILIPS_FCV1236D,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
@@ -453,7 +430,36 @@ struct usb_device_id em28xx_id_table [] = {
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
 
-/* EEPROM hash table for devices with generic USB IDs */
+/*
+ *  Reset sequences for analog/digital modes
+ */
+
+/* Board Hauppauge WinTV HVR 900 analog */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
+       {EM28XX_R08_GPIO,       0x2d,   ~EM_GPIO_4,     10},
+       {0x05,                  0xff,   0x10,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 digital */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
+       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x04,   0x0f,           10},
+       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 tuner_callback */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       0,              EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+/*
+ * EEPROM hash table for devices with generic USB IDs
+ */
 static struct em28xx_hash_table em28xx_eeprom_hash [] = {
        /* P/N: SA 60002070465 Tuner: TVF7533-MF */
        {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
@@ -465,79 +471,113 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
        {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
 };
 
+int em28xx_tuner_callback(void *ptr, int command, int arg)
+{
+       int rc = 0;
+       struct em28xx *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC2028)
+               return 0;
+
+       if (command != XC2028_TUNER_RESET)
+               return 0;
+
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               rc = em28xx_gpio_set(dev, dev->tun_analog_gpio);
+       else
+               rc = em28xx_gpio_set(dev, dev->tun_digital_gpio);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
+
+static void em28xx_set_model(struct em28xx *dev)
+{
+       dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+       dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
+       dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+       dev->decoder = em28xx_boards[dev->model].decoder;
+       dev->video_inputs = em28xx_boards[dev->model].vchannels;
+       dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+       dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+       dev->has_dvb = em28xx_boards[dev->model].has_dvb;
+}
+
 /* Since em28xx_pre_card_setup() requires a proper dev->model,
  * this won't work for boards with generic PCI IDs
  */
 void em28xx_pre_card_setup(struct em28xx *dev)
 {
+       int rc;
+
+       rc = em28xx_read_reg(dev, EM2880_R04_GPO);
+       if (rc >= 0)
+               dev->reg_gpo = rc;
+
+       dev->wait_after_write = 5;
+       rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+       if (rc > 0) {
+               switch (rc) {
+               case CHIP_ID_EM2883:
+                       em28xx_info("chip ID is em2882/em2883\n");
+                       dev->wait_after_write = 0;
+                       break;
+               default:
+                       em28xx_info("em28xx chip ID = %d\n", rc);
+               }
+       }
+       em28xx_set_model(dev);
+
        /* request some modules */
        switch (dev->model) {
        case EM2880_BOARD_TERRATEC_PRODIGY_XS:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_TERRATEC_HYBRID_XS:
-               em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
-               em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
-               em28xx_write_regs(dev, 0x08, "\xff", 1);
-               em28xx_write_regs(dev, 0x04, "\x00", 1);
-               msleep(100);
-               em28xx_write_regs(dev, 0x04, "\x08", 1);
-               msleep(100);
-               em28xx_write_regs(dev, 0x08, "\xff", 1);
-               msleep(50);
-               em28xx_write_regs(dev, 0x08, "\x2d", 1);
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
                msleep(50);
-               em28xx_write_regs(dev, 0x08, "\x3d", 1);
+
+               /* Sets GPO/GPIO sequences for this device */
+               dev->analog_gpio      = hauppauge_wintv_hvr_900_analog;
+               dev->digital_gpio     = hauppauge_wintv_hvr_900_digital;
+               dev->tun_analog_gpio  = hauppauge_wintv_hvr_900_tuner_callback;
+               dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
+
                break;
        }
+
+       em28xx_gpio_set(dev, dev->tun_analog_gpio);
+       em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+
+       /* Unlock device */
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
 }
 
-static int em28xx_tuner_callback(void *ptr, int command, int arg)
+static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
 {
-       int rc = 0;
-       struct em28xx *dev = ptr;
+       memset(ctl, 0, sizeof(*ctl));
 
-       if (dev->tuner_type != TUNER_XC2028)
-               return 0;
-
-       switch (command) {
-       case XC2028_TUNER_RESET:
-       {
-               /* GPIO and initialization codes for analog TV and radio
-                  This code should be complemented for DTV, since reset
-                  codes are different.
-                */
-
-               dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
-               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
-
-               if (dev->analog_gpio) {
-                       char gpio0 = dev->analog_gpio & 0xff;
-                       char gpio1 = (dev->analog_gpio >> 8) & 0xff;
-                       char gpio4 = dev->analog_gpio >> 24;
-
-                       if (gpio4) {
-                               dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
-                               msleep(140);
-                       }
-
-                       msleep(6);
-                       dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
-                       msleep(10);
-                       dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
-                       msleep(5);
-               }
+       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+       ctl->max_len = 64;
+       ctl->mts = em28xx_boards[dev->model].mts_firmware;
 
+       switch (dev->model) {
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+               ctl->demod = XC3028_FE_ZARLINK456;
                break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               /* FIXME: Better to specify the needed IF */
+               ctl->demod = XC3028_FE_DEFAULT;
+               break;
+       default:
+               ctl->demod = XC3028_FE_OREN538;
        }
-       }
-       return rc;
 }
 
 static void em28xx_config_tuner(struct em28xx *dev)
 {
        struct v4l2_priv_tun_config  xc2028_cfg;
-       struct xc2028_ctrl           ctl;
        struct tuner_setup           tun_setup;
        struct v4l2_frequency        f;
 
@@ -552,11 +592,9 @@ static void em28xx_config_tuner(struct em28xx *dev)
        em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
 
        if (dev->tuner_type == TUNER_XC2028) {
-               memset(&ctl, 0, sizeof(ctl));
+               struct xc2028_ctrl           ctl;
 
-               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
-               ctl.max_len = 64;
-               ctl.mts = em28xx_boards[dev->model].mts_firmware;
+               em28xx_setup_xc3028(dev, &ctl);
 
                xc2028_cfg.tuner = TUNER_XC2028;
                xc2028_cfg.priv  = &ctl;
@@ -654,19 +692,6 @@ static int em28xx_hint_board(struct em28xx *dev)
        return -1;
 }
 
-
-static void em28xx_set_model(struct em28xx *dev)
-{
-       dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
-       dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
-       dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
-       dev->decoder = em28xx_boards[dev->model].decoder;
-       dev->video_inputs = em28xx_boards[dev->model].vchannels;
-       dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
-       dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
-       dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
-}
-
 /* ----------------------------------------------------------------------- */
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
 {
index c1caaa855b99b16e9d09962a0000e5d48817bd5f..f8c41d8c74c4173be55d517b1647b2bf244d27bf 100644 (file)
 
 /* #define ENABLE_DEBUG_ISOC_FRAMES */
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
 #define em28xx_coredbg(fmt, arg...) do {\
        if (core_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
 
-static unsigned int reg_debug = 0;
+static unsigned int reg_debug;
 module_param(reg_debug,int,0644);
 MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
 
 #define em28xx_regdbg(fmt, arg...) do {\
        if (reg_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
-
-static unsigned int isoc_debug = 0;
-module_param(isoc_debug,int,0644);
-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
-
-#define em28xx_isocdbg(fmt, arg...) do {\
-       if (isoc_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
 
 static int alt = EM28XX_PINOUT;
 module_param(alt, int, 0644);
 MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
 
-
-/*
- * em28xx_request_buffers()
- * allocate a number of buffers
- */
-u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
-{
-       const size_t imagesize = PAGE_ALIGN(dev->frame_size);   /*needs to be page aligned cause the buffers can be mapped individually! */
-       void *buff = NULL;
-       u32 i;
-       em28xx_coredbg("requested %i buffers with size %zi\n",
-                       count, imagesize);
-       if (count > EM28XX_NUM_FRAMES)
-               count = EM28XX_NUM_FRAMES;
-
-       dev->num_frames = count;
-       while (dev->num_frames > 0) {
-               if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
-                       memset(buff, 0, dev->num_frames * imagesize);
-                       break;
-               }
-               dev->num_frames--;
-       }
-
-       for (i = 0; i < dev->num_frames; i++) {
-               dev->frame[i].bufmem = buff + i * imagesize;
-               dev->frame[i].buf.index = i;
-               dev->frame[i].buf.m.offset = i * imagesize;
-               dev->frame[i].buf.length = dev->frame_size;
-               dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               dev->frame[i].buf.sequence = 0;
-               dev->frame[i].buf.field = V4L2_FIELD_NONE;
-               dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
-               dev->frame[i].buf.flags = 0;
-       }
-       return dev->num_frames;
-}
-
-/*
- * em28xx_queue_unusedframes()
- * add all frames that are not currently in use to the inbuffer queue
- */
-void em28xx_queue_unusedframes(struct em28xx *dev)
-{
-       unsigned long lock_flags;
-       u32 i;
-
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].state == F_UNUSED) {
-                       dev->frame[i].state = F_QUEUED;
-                       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-                       list_add_tail(&dev->frame[i].frame, &dev->inqueue);
-                       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-               }
-}
-
-/*
- * em28xx_release_buffers()
- * free frame buffers
- */
-void em28xx_release_buffers(struct em28xx *dev)
-{
-       if (dev->num_frames) {
-               vfree(dev->frame[0].bufmem);
-               dev->num_frames = 0;
-       }
-}
+/* FIXME */
+#define em28xx_isocdbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
 
 /*
  * em28xx_read_reg_req()
@@ -148,11 +77,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              0x0000, reg, buf, len, HZ);
 
-       if (reg_debug){
+       if (reg_debug) {
                printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
-               for (byte = 0; byte < len; byte++) {
+               for (byte = 0; byte < len; byte++)
                        printk(" %02x", (unsigned char)buf[byte]);
-               }
+
                printk("\n");
        }
 
@@ -205,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        unsigned char *bufs;
 
        if (dev->state & DEV_DISCONNECTED)
-               return(-ENODEV);
+               return -ENODEV;
+
+       if (len < 1)
+               return -EINVAL;
 
        bufs = kmalloc(len, GFP_KERNEL);
 
@@ -214,8 +146,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        if (reg_debug) {
                int i;
                for (i = 0; i < len; ++i)
-                       printk (" %02x", (unsigned char)buf[i]);
-               printk ("\n");
+                       printk(" %02x", (unsigned char)buf[i]);
+               printk("\n");
        }
 
        if (!bufs)
@@ -224,14 +156,32 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
        ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              0x0000, reg, bufs, len, HZ);
-       msleep(5);              /* FIXME: magic number */
+       if (dev->wait_after_write)
+               msleep(dev->wait_after_write);
+
        kfree(bufs);
        return ret;
 }
 
 int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
 {
-       return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+       int rc;
+
+       rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+
+       /* Stores GPO/GPIO values at the cache, if changed
+          Only write values should be stored, since input on a GPIO
+          register will return the input bits.
+          Not sure what happens on reading GPO register.
+        */
+       if (rc >= 0) {
+               if (reg == EM2880_R04_GPO)
+                       dev->reg_gpo = buf[0];
+               else if (reg == EM28XX_R08_GPIO)
+                       dev->reg_gpio = buf[0];
+       }
+
+       return rc;
 }
 
 /*
@@ -244,9 +194,20 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
 {
        int oldval;
        u8 newval;
-       if ((oldval = em28xx_read_reg(dev, reg)) < 0)
+
+       /* Uses cache for gpo/gpio registers */
+       if (reg == EM2880_R04_GPO)
+               oldval = dev->reg_gpo;
+       else if (reg == EM28XX_R08_GPIO)
+               oldval = dev->reg_gpio;
+       else
+               oldval = em28xx_read_reg(dev, reg);
+
+       if (oldval < 0)
                return oldval;
+
        newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
+
        return em28xx_write_regs(dev, reg, &newval, 1);
 }
 
@@ -258,20 +219,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
 {
        int ret, i;
        u8 addr = reg & 0x7f;
-       if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
+
+       ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2);
+       if (ret < 0)
                return ret;
-       if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
+
+       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
+       if (ret < 0)
                return ret;
 
        /* Wait up to 50 ms for AC97 command to complete */
        for (i = 0; i < 10; i++) {
-               if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
+               ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
+               if (ret < 0)
                        return ret;
+
                if (!(ret & 0x01))
                        return 0;
                msleep(5);
        }
-       em28xx_warn ("AC97 command still being executed: not handled properly!\n");
+       em28xx_warn("AC97 command still being executed: not handled properly!\n");
        return 0;
 }
 
@@ -289,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
                else
                        input = EM2800_AUDIO_SRC_TUNER;
 
-               ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
+               ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
                if (ret < 0)
                        return ret;
        }
@@ -315,7 +282,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
                }
        }
 
-       ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
+       ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
        if (ret < 0)
                return ret;
        msleep(5);
@@ -323,11 +290,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
        /* Sets AC97 mixer registers
           This is seems to be needed, even for non-ac97 configs
         */
-       ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
+       ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
        if (ret < 0)
                return ret;
 
-       ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
+       ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
 
        return ret;
 }
@@ -343,7 +310,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
 
        /* Mute */
        s[1] |= 0x80;
-       ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+       ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
 
        if (ret < 0)
                return ret;
@@ -354,7 +321,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
        if (!dev->mute)
                xclk |= 0x80;
 
-       ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
+       ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7);
        if (ret < 0)
                return ret;
        msleep(10);
@@ -365,7 +332,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
        /* Unmute device */
        if (!dev->mute)
                s[1] &= ~0x80;
-       ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+       ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
 
        return ret;
 }
@@ -373,50 +340,68 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
 
 int em28xx_colorlevels_set_default(struct em28xx *dev)
 {
-       em28xx_write_regs(dev, YGAIN_REG, "\x10", 1);   /* contrast */
-       em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */
-       em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1);  /* saturation */
-       em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1);
-
-       em28xx_write_regs(dev, GAMMA_REG, "\x20", 1);
-       em28xx_write_regs(dev, RGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, GGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, BGAIN_REG, "\x20", 1);
-       em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1);
-       em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1);
-       return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1);    /* contrast */
+       em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1);  /* brightness */
+       em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1);   /* saturation */
+       em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1);
+
+       em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1);
+       em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1);
+       em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1);
+       return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1);
 }
 
 int em28xx_capture_start(struct em28xx *dev, int start)
 {
-       int ret;
+       int rc;
        /* FIXME: which is the best order? */
        /* video registers are sampled by VREF */
-       if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00,
-                                         0x10)) < 0)
-               return ret;
+       rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
+                                  start ? 0x10 : 0x00, 0x10);
+       if (rc < 0)
+               return rc;
+
+       if (!start) {
+               /* disable video capture */
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1);
+               return rc;
+       }
+
        /* enable video capture */
-       return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1);
+       rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1);
+       else
+               rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1);
+
+       msleep(6);
+
+       return rc;
 }
 
 int em28xx_outfmt_set_yuv422(struct em28xx *dev)
 {
-       em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1);
-       em28xx_write_regs(dev, VINMODE_REG, "\x10", 1);
-       return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
+       em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1);
+       em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1);
+       return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1);
 }
 
 static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
                                  u8 ymin, u8 ymax)
 {
-       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
+       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
+                       xmin, ymin, xmax, ymax);
 
-       em28xx_write_regs(dev, XMIN_REG, &xmin, 1);
-       em28xx_write_regs(dev, XMAX_REG, &xmax, 1);
-       em28xx_write_regs(dev, YMIN_REG, &ymin, 1);
-       return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
+       em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
+       em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
+       em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
+       return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
 }
 
 static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
@@ -426,34 +411,36 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
        u8 cheight = height;
        u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
 
-       em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7),
+       em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
+                       (width | (overflow & 2) << 7),
                        (height | (overflow & 1) << 8));
 
-       em28xx_write_regs(dev, HSTART_REG, &hstart, 1);
-       em28xx_write_regs(dev, VSTART_REG, &vstart, 1);
-       em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1);
-       em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1);
-       return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
+       em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
+       em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
+       return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
 }
 
 static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
 {
        u8 mode;
        /* the em2800 scaler only supports scaling down to 50% */
-       if(dev->is_em2800)
+       if (dev->is_em2800)
                mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
        else {
                u8 buf[2];
                buf[0] = h;
                buf[1] = h >> 8;
-               em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);
+               em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
                buf[0] = v;
                buf[1] = v >> 8;
-               em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);
-               /* it seems that both H and V scalers must be active to work correctly */
+               em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
+               /* it seems that both H and V scalers must be active
+                  to work correctly */
                mode = (h || v)? 0x30: 0x00;
        }
-       return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);
+       return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
 }
 
 /* FIXME: this only function read values from dev */
@@ -469,376 +456,271 @@ int em28xx_resolution_set(struct em28xx *dev)
        return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
 }
 
-
-/******************* isoc transfer handling ****************************/
-
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
-static void em28xx_isoc_dump(struct urb *urb)
+int em28xx_set_alternate(struct em28xx *dev)
 {
-       int len = 0;
-       int ntrans = 0;
+       int errCode, prev_alt = dev->alt;
        int i;
+       unsigned int min_pkt_size = dev->width * 2 + 4;
 
-       printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
-              urb->start_frame, urb->number_of_packets,
-              urb->error_count);
-       for (i = 0; i < urb->number_of_packets; i++) {
-               unsigned char *buf =
-                               urb->transfer_buffer +
-                               urb->iso_frame_desc[i].offset;
-               int alen = urb->iso_frame_desc[i].actual_length;
-               if (alen > 0) {
-                       if (buf[0] == 0x88) {
-                               ntrans++;
-                               len += alen;
-                       } else if (buf[0] == 0x22) {
-                               printk(KERN_DEBUG
-                                               "= l=%d nt=%d bpp=%d\n",
-                               len - 4 * ntrans, ntrans,
-                               ntrans == 0 ? 0 : len / ntrans);
-                               ntrans = 1;
-                               len = alen;
-                       } else
-                               printk(KERN_DEBUG "!\n");
+       /* When image size is bigger than a certain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->width * 2 * dev->height > 720 * 240 * 2)
+               min_pkt_size *= 2;
+
+       for (i = 0; i < dev->num_alt; i++) {
+               /* stop when the selected alt setting offers enough bandwidth */
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+                       dev->alt = i;
+                       break;
+               /* otherwise make sure that we end up with the maximum bandwidth
+                  because the min_pkt_size equation might be wrong...
+               */
+               } else if (dev->alt_max_pkt_size[i] >
+                          dev->alt_max_pkt_size[dev->alt])
+                       dev->alt = i;
+       }
+
+       if (dev->alt != prev_alt) {
+               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
+               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->max_pkt_size);
+               errCode = usb_set_interface(dev->udev, 0, dev->alt);
+               if (errCode < 0) {
+                       em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
+                                       dev->alt, errCode);
+                       return errCode;
                }
-               printk(KERN_DEBUG "   n=%d s=%d al=%d %x\n", i,
-                      urb->iso_frame_desc[i].status,
-                      urb->iso_frame_desc[i].actual_length,
-                      (unsigned int)
-                                      *((unsigned char *)(urb->transfer_buffer +
-                                      urb->iso_frame_desc[i].
-                                      offset)));
        }
+       return 0;
 }
-#endif
 
-static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
-                                   unsigned long *lock_flags, unsigned char buf)
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
 {
-       if (!(buf & 0x01)) {
-               if ((*f)->state == F_GRABBING) {
-                       /*previous frame is incomplete */
-                       if ((*f)->fieldbytesused < dev->field_size) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
-                                        dev->field_size-(*f)->fieldbytesused);
-                       } else {
-                               (*f)->state = F_DONE;
-                               (*f)->buf.bytesused = dev->frame_size;
-                       }
-               }
-               if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
-                       /* move current frame to outqueue and get next free buffer from inqueue */
-                       spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
-                       list_move_tail(&(*f)->frame, &dev->outqueue);
-                       if (!list_empty(&dev->inqueue))
-                               (*f) = list_entry(dev-> inqueue.next,
-                       struct em28xx_frame_t,frame);
-                       else
-                               (*f) = NULL;
-                       spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
-               }
-               if (!(*f)) {
-                       em28xx_isocdbg ("new frame but no buffer is free");
-                       return -1;
-               }
-               do_gettimeofday(&(*f)->buf.timestamp);
-               (*f)->buf.sequence = ++dev->frame_count;
-               (*f)->buf.field = V4L2_FIELD_INTERLACED;
-               (*f)->state = F_GRABBING;
-               (*f)->buf.bytesused = 0;
-               (*f)->top_field = 1;
-               (*f)->fieldbytesused = 0;
-       } else {
-                                       /* acquiring bottom field */
-               if ((*f)->state == F_GRABBING) {
-                       if (!(*f)->top_field) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
-                       } else if ((*f)-> fieldbytesused < dev->field_size - 172) {
-                               (*f)->state = F_ERROR;
-                               em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
-                                        dev->field_size-(*f)->fieldbytesused);
-                       } else {
-                               (*f)->top_field = 0;
-                               (*f)->fieldbytesused = 0;
-                       }
+       int rc = 0;
+
+       if (!gpio)
+               return rc;
+
+       dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
+       else
+               dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1);
+       msleep(6);
+
+       /* Send GPIO reset sequences specified at board entry */
+       while (gpio->sleep >= 0) {
+               if (gpio->reg >= 0) {
+                       rc = em28xx_write_reg_bits(dev,
+                                                  gpio->reg,
+                                                  gpio->val,
+                                                  gpio->mask);
+                       if (rc < 0)
+                               return rc;
                }
+               if (gpio->sleep > 0)
+                       msleep(gpio->sleep);
+
+               gpio++;
        }
-       return (0);
+       return rc;
 }
 
-static inline void em28xx_isoc_video_copy(struct em28xx *dev,
-                                         struct em28xx_frame_t **f, unsigned char *buf, int len)
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
 {
-       void *fieldstart, *startwrite, *startread;
-       int linesdone, currlinedone, offset, lencopy,remain;
+       if (dev->mode == set_mode)
+               return 0;
 
-       if(dev->frame_size != (*f)->buf.length){
-               em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
-               return;
+       if (set_mode == EM28XX_MODE_UNDEFINED) {
+               dev->mode = set_mode;
+               return 0;
        }
 
-       if ((*f)->fieldbytesused + len > dev->field_size)
-               len =dev->field_size - (*f)->fieldbytesused;
-
-       if (buf[0] != 0x88 && buf[0] != 0x22) {
-               em28xx_isocdbg("frame is not complete\n");
-               startread = buf;
-               len+=4;
-       } else
-               startread = buf + 4;
-
-       remain = len;
+       dev->mode = set_mode;
 
-       if ((*f)->top_field)
-               fieldstart = (*f)->bufmem;
+       if (dev->mode == EM28XX_DIGITAL_MODE)
+               return em28xx_gpio_set(dev, dev->digital_gpio);
        else
-               fieldstart = (*f)->bufmem + dev->bytesperline;
-
-       linesdone = (*f)->fieldbytesused / dev->bytesperline;
-       currlinedone = (*f)->fieldbytesused % dev->bytesperline;
-       offset = linesdone * dev->bytesperline * 2 + currlinedone;
-       startwrite = fieldstart + offset;
-       lencopy = dev->bytesperline - currlinedone;
-       lencopy = lencopy > remain ? remain : lencopy;
-
-       memcpy(startwrite, startread, lencopy);
-       remain -= lencopy;
-
-       while (remain > 0) {
-               startwrite += lencopy + dev->bytesperline;
-               startread += lencopy;
-               if (dev->bytesperline > remain)
-                       lencopy = remain;
-               else
-                       lencopy = dev->bytesperline;
-
-               memcpy(startwrite, startread, lencopy);
-               remain -= lencopy;
-       }
-
-       (*f)->fieldbytesused += len;
+               return em28xx_gpio_set(dev, dev->analog_gpio);
 }
+EXPORT_SYMBOL_GPL(em28xx_set_mode);
+
+/* ------------------------------------------------------------------
+       URB control
+   ------------------------------------------------------------------*/
 
 /*
- * em28xx_isoIrq()
- * handles the incoming isoc urbs and fills the frames from our inqueue
+ * IRQ callback, called by URB callback
  */
-static void em28xx_isocIrq(struct urb *urb)
+static void em28xx_irq_callback(struct urb *urb)
 {
-       struct em28xx *dev = urb->context;
-       int i, status;
-       struct em28xx_frame_t **f;
-       unsigned long lock_flags;
-
-       if (!dev)
-               return;
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
-       if (isoc_debug>1)
-               em28xx_isoc_dump(urb);
-#endif
-
-       if (urb->status == -ENOENT)
-               return;
-
-       f = &dev->frame_current;
-
-       if (dev->stream == STREAM_INTERRUPT) {
-               dev->stream = STREAM_OFF;
-               if ((*f))
-                       (*f)->state = F_QUEUED;
-               em28xx_isocdbg("stream interrupted");
-               wake_up_interruptible(&dev->wait_stream);
-       }
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return;
-
-       if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
-               if (!(*f))
-                       (*f) = list_entry(dev->inqueue.next,
-               struct em28xx_frame_t, frame);
-
-               for (i = 0; i < urb->number_of_packets; i++) {
-                       unsigned char *buf = urb->transfer_buffer +
-                                       urb->iso_frame_desc[i].offset;
-                       int len = urb->iso_frame_desc[i].actual_length - 4;
-
-                       if (urb->iso_frame_desc[i].status) {
-                               em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
-                                       urb->iso_frame_desc[i].actual_length,
-                                       urb->iso_frame_desc[i].status);
-                               if (urb->iso_frame_desc[i].status != -EPROTO)
-                                       continue;
-                       }
-                       if (urb->iso_frame_desc[i].actual_length <= 0) {
-                               em28xx_isocdbg("packet %d is empty",i);
-                               continue;
-                       }
-                       if (urb->iso_frame_desc[i].actual_length >
-                           urb->iso_frame_desc[i].length) {
-                               em28xx_isocdbg("packet bigger than packet size");
-                               continue;
-                       }
-                       /*new frame */
-                       if (buf[0] == 0x22 && buf[1] == 0x5a) {
-                               em28xx_isocdbg("Video frame, length=%i!",len);
-
-                               if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
-                               break;
-                       } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
-                               em28xx_isocdbg("VBI HEADER!!!");
-                       }
+       struct em28xx_dmaqueue  *dma_q = urb->context;
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       int rc, i;
 
-                       /* actual copying */
-                       if ((*f)->state == F_GRABBING) {
-                               em28xx_isoc_video_copy(dev,f,buf, len);
-                       }
-               }
-       }
+       /* Copy data from URB */
+       spin_lock(&dev->slock);
+       rc = dev->isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock(&dev->slock);
 
+       /* Reset urb buffers */
        for (i = 0; i < urb->number_of_packets; i++) {
                urb->iso_frame_desc[i].status = 0;
                urb->iso_frame_desc[i].actual_length = 0;
        }
-
        urb->status = 0;
-       if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
-               em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
-               dev->state |= DEV_MISCONFIGURED;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               em28xx_isocdbg("urb resubmit failed (error=%i)\n",
+                              urb->status);
        }
-       wake_up_interruptible(&dev->wait_frame);
-       return;
 }
 
 /*
- * em28xx_uninit_isoc()
- * deallocates the buffers and urbs allocated during em28xx_init_iosc()
+ * Stop and Deallocate URBs
  */
 void em28xx_uninit_isoc(struct em28xx *dev)
 {
+       struct urb *urb;
        int i;
 
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               if (dev->urb[i]) {
-                       usb_kill_urb(dev->urb[i]);
-                       if (dev->transfer_buffer[i]) {
+       em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
+
+       dev->isoc_ctl.nfields = -1;
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+                       usb_kill_urb(urb);
+                       usb_unlink_urb(urb);
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
                                usb_buffer_free(dev->udev,
-                                               dev->urb[i]->transfer_buffer_length,
-                                               dev->transfer_buffer[i],
-                                               dev->urb[i]->transfer_dma);
+                                       urb->transfer_buffer_length,
+                                       dev->isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
                        }
-                       usb_free_urb(dev->urb[i]);
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
                }
-               dev->urb[i] = NULL;
-               dev->transfer_buffer[i] = NULL;
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
        }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+
        em28xx_capture_start(dev, 0);
 }
+EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
 
 /*
- * em28xx_init_isoc()
- * allocates transfer buffers and submits the urbs for isoc transfer
+ * Allocate URBs and start IRQ
  */
-int em28xx_init_isoc(struct em28xx *dev)
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
 {
-       /* change interface to 3 which allows the biggest packet sizes */
-       int i, errCode;
-       int sb_size;
-
-       em28xx_set_alternate(dev);
-       sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
-
-       /* reset streaming vars */
-       dev->frame_current = NULL;
-       dev->frame_count = 0;
-
-       /* allocate urbs */
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               struct urb *urb;
-               int j;
-               /* allocate transfer buffer */
-               urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
-               if (!urb){
-                       em28xx_errdev("cannot alloc urb %i\n", i);
+       struct em28xx_dmaqueue *dma_q = &dev->vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+       int rc;
+
+       em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
+
+       /* De-allocates all pending stuff */
+       em28xx_uninit_isoc(dev);
+
+       dev->isoc_ctl.isoc_copy = isoc_copy;
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               em28xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               em28xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.max_pkt_size = max_pkt_size;
+       dev->isoc_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
                        em28xx_uninit_isoc(dev);
                        return -ENOMEM;
                }
-               dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
-                                                          GFP_KERNEL,
-                                                          &urb->transfer_dma);
-               if (!dev->transfer_buffer[i]) {
-                       em28xx_errdev
-                                       ("unable to allocate %i bytes for transfer buffer %i\n",
-                                        sb_size, i);
+               dev->isoc_ctl.urb[i] = urb;
+
+               dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       em28xx_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt()?" while in int":"");
                        em28xx_uninit_isoc(dev);
-                       usb_free_urb(urb);
                        return -ENOMEM;
                }
-               memset(dev->transfer_buffer[i], 0, sb_size);
-               urb->dev = dev->udev;
-               urb->context = dev;
-               urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = 1;
-               urb->transfer_buffer = dev->transfer_buffer[i];
-               urb->complete = em28xx_isocIrq;
-               urb->number_of_packets = EM28XX_NUM_PACKETS;
-               urb->transfer_buffer_length = sb_size;
-               for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
-                       urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
-                       urb->iso_frame_desc[j].length = dev->max_pkt_size;
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               /* FIXME: this is a hack - should be
+                       'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
+                       should also be using 'desc.bInterval'
+                */
+               pipe = usb_rcvisocpipe(dev->udev,
+                       dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
+
+               usb_fill_int_urb(urb, dev->udev, pipe,
+                                dev->isoc_ctl.transfer_buffer[i], sb_size,
+                                em28xx_irq_callback, dma_q, 1);
+
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP;
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                               dev->isoc_ctl.max_pkt_size;
+                       k += dev->isoc_ctl.max_pkt_size;
                }
-               dev->urb[i] = urb;
        }
 
-       /* submit urbs */
-       em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
-                      EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
-       for (i = 0; i < EM28XX_NUM_BUFS; i++) {
-               errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
-               if (errCode) {
-                       em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
-                                     errCode);
-                       em28xx_uninit_isoc(dev);
-                       return errCode;
-               }
-       }
-
-       return 0;
-}
-
-int em28xx_set_alternate(struct em28xx *dev)
-{
-       int errCode, prev_alt = dev->alt;
-       int i;
-       unsigned int min_pkt_size = dev->bytesperline+4;
-
-       /* When image size is bigger than a ceirtain value,
-          the frame size should be increased, otherwise, only
-          green screen will be received.
-        */
-       if (dev->frame_size > 720*240*2)
-               min_pkt_size *= 2;
+       init_waitqueue_head(&dma_q->wq);
 
-       for (i = 0; i < dev->num_alt; i++)
-               if (dev->alt_max_pkt_size[i] >= min_pkt_size)
-                       break;
-       dev->alt = i;
+       em28xx_capture_start(dev, 1);
 
-       if (dev->alt != prev_alt) {
-               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->alt);
-               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
-               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
-                              dev->alt, dev->max_pkt_size);
-               errCode = usb_set_interface(dev->udev, 0, dev->alt);
-               if (errCode < 0) {
-                       em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
-                                       dev->alt, errCode);
-                       return errCode;
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       em28xx_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       em28xx_uninit_isoc(dev);
+                       return rc;
                }
        }
+
        return 0;
 }
+EXPORT_SYMBOL_GPL(em28xx_init_isoc);
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
new file mode 100644 (file)
index 0000000..7df8157
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ DVB device driver for em28xx
+
+ (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
+       - Fixes for the driver to properly work with HVR-950
+
+ (c) 2008 Aidan Thornton <makosoft@googlemail.com>
+
+ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
+       (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+       (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+
+#include "em28xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+
+#include "lgdt330x.h"
+#include "zl10353.h"
+
+MODULE_DESCRIPTION("driver for em28xx based DVB cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+#define EM28XX_DVB_NUM_BUFS 5
+#define EM28XX_DVB_MAX_PACKETSIZE 564
+#define EM28XX_DVB_MAX_PACKETS 64
+
+struct em28xx_dvb {
+       struct dvb_frontend        *frontend;
+
+       /* feed count management */
+       struct mutex               lock;
+       int                        nfeeds;
+
+       /* general boilerplate stuff */
+       struct dvb_adapter         adapter;
+       struct dvb_demux           demux;
+       struct dmxdev              dmxdev;
+       struct dmx_frontend        fe_hw;
+       struct dmx_frontend        fe_mem;
+       struct dvb_net             net;
+};
+
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(1, "URB status %d [%s].\n", status, errmsg);
+       } else {
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       int i;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
+                                urb->iso_frame_desc[i].offset,
+                                urb->iso_frame_desc[i].actual_length);
+       }
+
+       return 0;
+}
+
+static int start_streaming(struct em28xx_dvb *dvb)
+{
+       int rc;
+       struct em28xx *dev = dvb->adapter.priv;
+
+       usb_set_interface(dev->udev, 0, 1);
+       rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       if (rc < 0)
+               return rc;
+
+       return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
+                               EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
+                               dvb_isoc_copy);
+}
+
+static int stop_streaming(struct em28xx_dvb *dvb)
+{
+       struct em28xx *dev = dvb->adapter.priv;
+
+       em28xx_uninit_isoc(dev);
+
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
+       return 0;
+}
+
+static int start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int rc, ret;
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds++;
+       rc = dvb->nfeeds;
+
+       if (dvb->nfeeds == 1) {
+               ret = start_streaming(dvb);
+               if (ret < 0)
+                       rc = ret;
+       }
+
+       mutex_unlock(&dvb->lock);
+       return rc;
+}
+
+static int stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int err = 0;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds--;
+
+       if (0 == dvb->nfeeds)
+               err = stop_streaming(dvb);
+
+       mutex_unlock(&dvb->lock);
+       return err;
+}
+
+
+
+/* ------------------------------------------------------------------ */
+static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct em28xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       else
+               return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct lgdt330x_config em2880_lgdt3303_dev = {
+       .demod_address = 0x0e,
+       .demod_chip = LGDT3303,
+};
+
+static struct zl10353_config em28xx_zl10353_with_xc3028 = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .parallel_ts = 1,
+       .if2 = 45600,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int attach_xc3028(u8 addr, struct em28xx *dev)
+{
+       struct dvb_frontend *fe;
+       struct xc2028_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.i2c_adap  = &dev->i2c_adap;
+       cfg.i2c_addr  = addr;
+       cfg.callback  = em28xx_tuner_callback;
+
+       if (!dev->dvb->frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc3028\n",
+                      dev->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                      dev->name);
+               dvb_frontend_detach(dev->dvb->frontend);
+               dvb_unregister_frontend(dev->dvb->frontend);
+               dev->dvb->frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int register_dvb(struct em28xx_dvb *dvb,
+                struct module *module,
+                struct em28xx *dev,
+                struct device *device)
+{
+       int result;
+
+       mutex_init(&dvb->lock);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+                                     adapter_nr);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_adapter;
+       }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dvb;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = start_feed;
+       dvb->demux.stop_feed  = stop_feed;
+
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+static void unregister_dvb(struct em28xx_dvb *dvb)
+{
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+
+static int dvb_init(struct em28xx *dev)
+{
+       int result = 0;
+       struct em28xx_dvb *dvb;
+
+       dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
+
+       if (dvb == NULL) {
+               printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev->dvb = dvb;
+
+       em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       /* init frontend */
+       switch (dev->model) {
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+               dvb->frontend = dvb_attach(lgdt330x_attach,
+                                          &em2880_lgdt3303_dev,
+                                          &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+               dvb->frontend = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_with_xc3028,
+                                          &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       default:
+               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+                               " isn't supported yet\n",
+                      dev->name);
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      dev->name);
+               result = -EINVAL;
+               goto out_free;
+       }
+
+       /* register everything */
+       result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+       if (result < 0)
+               goto out_free;
+
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
+       return 0;
+
+out_free:
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       kfree(dvb);
+       dev->dvb = NULL;
+       return result;
+}
+
+static int dvb_fini(struct em28xx *dev)
+{
+       if (dev->dvb) {
+               unregister_dvb(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct em28xx_ops dvb_ops = {
+       .id   = EM28XX_DVB,
+       .name = "Em28xx dvb Extension",
+       .init = dvb_init,
+       .fini = dvb_fini,
+};
+
+static int __init em28xx_dvb_register(void)
+{
+       return em28xx_register_extension(&dvb_ops);
+}
+
+static void __exit em28xx_dvb_unregister(void)
+{
+       em28xx_unregister_extension(&dvb_ops);
+}
+
+module_init(em28xx_dvb_register);
+module_exit(em28xx_dvb_unregister);
index cacd04d46e99eb85145c9ee5e14ed0cff792bfde..6a78fd294cabfaef3343ce7fb9b94e85ea031bc0 100644 (file)
 
 /* ----------------------------------------------------------- */
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
-                       printk(fmt, ##args); } while (0)
-#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
-                       printk(KERN_DEBUG "%s at %s: " fmt, \
-                       dev->name, __FUNCTION__ , ##args); } while (0)
+
+#define dprintk1(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+       printk(fmt, ##args);                            \
+      }                                                        \
+} while (0)
+
+#define dprintk2(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(KERN_DEBUG "%s at %s: " fmt,     \
+                      dev->name, __func__ , ##args);   \
+      }                                                \
+} while (0)
 
 /*
  * em2800_i2c_send_max4()
@@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                return 0;
        for (i = 0; i < num; i++) {
                addr = msgs[i].addr << 1;
-               dprintk2(2,"%s %s addr=%x len=%d:",
+               dprintk2(2, "%s %s addr=%x len=%d:",
                         (msgs[i].flags & I2C_M_RD) ? "read" : "write",
                         i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (!msgs[i].len) {     /* no len: check only for device presence */
+               if (!msgs[i].len) { /* no len: check only for device presence */
                        if (dev->is_em2800)
                                rc = em2800_i2c_check_for_device(dev, addr);
                        else
                                rc = em28xx_i2c_check_for_device(dev, addr);
                        if (rc < 0) {
-                               dprintk2(2," no device\n");
+                               dprintk2(2, " no device\n");
                                return rc;
                        }
 
@@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                                rc = em28xx_i2c_recv_bytes(dev, addr,
                                                           msgs[i].buf,
                                                           msgs[i].len);
-                       if (i2c_debug>=2) {
-                               for (byte = 0; byte < msgs[i].len; byte++) {
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
                                        printk(" %02x", msgs[i].buf[byte]);
-                               }
                        }
                } else {
                        /* write bytes */
-                       if (i2c_debug>=2) {
+                       if (i2c_debug >= 2) {
                                for (byte = 0; byte < msgs[i].len; byte++)
                                        printk(" %02x", msgs[i].buf[byte]);
                        }
@@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
                }
                if (rc < 0)
                        goto err;
-               if (i2c_debug>=2)
+               if (i2c_debug >= 2)
                        printk("\n");
        }
 
        return num;
-      err:
-       dprintk2(2," ERROR: %i\n", rc);
+err:
+       dprintk2(2, " ERROR: %i\n", rc);
        return rc;
 }
 
@@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
                return -1;
 
        buf = 0;
-       if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
+
+       err = i2c_master_send(&dev->i2c_client, &buf, 1);
+       if (err != 1) {
                printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
                       dev->name, err);
                return -1;
@@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
                break;
        }
        printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
-                               em_eeprom->string_idx_table,em_eeprom->string1,
-                               em_eeprom->string2,em_eeprom->string3);
+                               em_eeprom->string_idx_table,
+                               em_eeprom->string1,
+                               em_eeprom->string2,
+                               em_eeprom->string3);
 
        return 0;
 }
@@ -430,58 +443,61 @@ static int attach_inform(struct i2c_client *client)
        struct em28xx *dev = client->adapter->algo_data;
 
        switch (client->addr << 1) {
-               case 0x86:
-               case 0x84:
-               case 0x96:
-               case 0x94:
-               {
-                       struct v4l2_priv_tun_config tda9887_cfg;
-
-                       struct tuner_setup tun_setup;
-
-                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-                       tun_setup.type = TUNER_TDA9887;
-                       tun_setup.addr = client->addr;
-
-                       em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
-
-                       tda9887_cfg.tuner = TUNER_TDA9887;
-                       tda9887_cfg.priv = &dev->tda9887_conf;
-                       em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
-                                               &tda9887_cfg);
-                       break;
-               }
-               case 0x42:
-                       dprintk1(1,"attach_inform: saa7114 detected.\n");
-                       break;
-               case 0x4a:
-                       dprintk1(1,"attach_inform: saa7113 detected.\n");
-                       break;
-               case 0xa0:
-                       dprintk1(1,"attach_inform: eeprom detected.\n");
-                       break;
-               case 0x60:
-               case 0x8e:
-               {
-                       struct IR_i2c *ir = i2c_get_clientdata(client);
-                       dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
-                       em28xx_set_ir(dev,ir);
-                       break;
-               }
-               case 0x80:
-               case 0x88:
-                       dprintk1(1,"attach_inform: msp34xx detected.\n");
-                       break;
-               case 0xb8:
-               case 0xba:
-                       dprintk1(1,"attach_inform: tvp5150 detected.\n");
-                       break;
-
-               default:
-                       if (!dev->tuner_addr)
-                               dev->tuner_addr = client->addr;
-
-                       dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
+       case 0x86:
+       case 0x84:
+       case 0x96:
+       case 0x94:
+       {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               struct tuner_setup tun_setup;
+
+               tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+               tun_setup.type = TUNER_TDA9887;
+               tun_setup.addr = client->addr;
+
+               em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
+                       &tun_setup);
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+               em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
+                                       &tda9887_cfg);
+               break;
+       }
+       case 0x42:
+               dprintk1(1, "attach_inform: saa7114 detected.\n");
+               break;
+       case 0x4a:
+               dprintk1(1, "attach_inform: saa7113 detected.\n");
+               break;
+       case 0xa0:
+               dprintk1(1, "attach_inform: eeprom detected.\n");
+               break;
+       case 0x60:
+       case 0x8e:
+       {
+               struct IR_i2c *ir = i2c_get_clientdata(client);
+               dprintk1(1, "attach_inform: IR detected (%s).\n",
+                       ir->phys);
+               em28xx_set_ir(dev, ir);
+               break;
+       }
+       case 0x80:
+       case 0x88:
+               dprintk1(1, "attach_inform: msp34xx detected.\n");
+               break;
+       case 0xb8:
+       case 0xba:
+               dprintk1(1, "attach_inform: tvp5150 detected.\n");
+               break;
+
+       default:
+               if (!dev->tuner_addr)
+                       dev->tuner_addr = client->addr;
+
+               dprintk1(1, "attach inform: detected I2C address %x\n",
+                               client->addr << 1);
 
        }
 
index 10da2fd8d9875072fe3476ed683266c450c4f08d..bb5807159b8d28638e46c01d7f0621861aedeed4 100644 (file)
 
 static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
-#define dprintk(fmt, arg...)   if (ir_debug) \
-       printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
+#define dprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+       }
 
 /* ----------------------------------------------------------------------- */
 
@@ -44,7 +46,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(&ir->c, &b, 1)) {
                dprintk("read error\n");
                return -EIO;
        }
@@ -74,24 +76,25 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char code;
 
        /* poll IR chip */
-       if (2 != i2c_master_recv(&ir->c,buf,2))
+       if (2 != i2c_master_recv(&ir->c, buf, 2))
                return -EIO;
 
        /* Does eliminate repeated parity code */
-       if (buf[1]==0xff)
+       if (buf[1] == 0xff)
                return 0;
 
-       ir->old=buf[1];
+       ir->old = buf[1];
 
        /* Rearranges bits to the right order */
-       code   ((buf[0]&0x01)<<5) | /* 0010 0000 */
+       code =   ((buf[0]&0x01)<<5) | /* 0010 0000 */
                 ((buf[0]&0x02)<<3) | /* 0001 0000 */
                 ((buf[0]&0x04)<<1) | /* 0000 1000 */
                 ((buf[0]&0x08)>>1) | /* 0000 0100 */
                 ((buf[0]&0x10)>>3) | /* 0000 0010 */
                 ((buf[0]&0x20)>>5);  /* 0000 0001 */
 
-       dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]);
+       dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
+                       code, buf[0]);
 
        /* return key */
        *ir_key = code;
@@ -106,15 +109,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
 
        /* poll IR chip */
 
-       if (3 != i2c_master_recv(&ir->c,buf,3)) {
+       if (3 != i2c_master_recv(&ir->c, buf, 3)) {
                dprintk("read error\n");
                return -EIO;
        }
 
        dprintk("key %02x\n", buf[2]&0x3f);
-       if (buf[0]!=0x00){
+       if (buf[0] != 0x00)
                return 0;
-       }
 
        *ir_key = buf[2]&0x3f;
        *ir_raw = buf[2]&0x3f;
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
new file mode 100644 (file)
index 0000000..9058bed
--- /dev/null
@@ -0,0 +1,88 @@
+#define EM_GPIO_0  (1 << 0)
+#define EM_GPIO_1  (1 << 1)
+#define EM_GPIO_2  (1 << 2)
+#define EM_GPIO_3  (1 << 3)
+#define EM_GPIO_4  (1 << 4)
+#define EM_GPIO_5  (1 << 5)
+#define EM_GPIO_6  (1 << 6)
+#define EM_GPIO_7  (1 << 7)
+
+#define EM_GPO_0   (1 << 0)
+#define EM_GPO_1   (1 << 1)
+#define EM_GPO_2   (1 << 2)
+#define EM_GPO_3   (1 << 3)
+
+/* em2800 registers */
+#define EM2800_R08_AUDIOSRC 0x08
+
+/* em28xx registers */
+
+       /* GPIO/GPO registers */
+#define EM2880_R04_GPO 0x04    /* em2880-em2883 only */
+#define EM28XX_R08_GPIO        0x08    /* em2820 or upper */
+
+#define EM28XX_R06_I2C_CLK     0x06
+#define EM28XX_R0A_CHIPID      0x0a
+#define EM28XX_R0C_USBSUSP     0x0c    /* */
+
+#define EM28XX_R0E_AUDIOSRC    0x0e
+#define EM28XX_R0F_XCLK        0x0f
+
+#define EM28XX_R10_VINMODE     0x10
+#define EM28XX_R11_VINCTRL     0x11
+#define EM28XX_R12_VINENABLE   0x12    /* */
+
+#define EM28XX_R14_GAMMA       0x14
+#define EM28XX_R15_RGAIN       0x15
+#define EM28XX_R16_GGAIN       0x16
+#define EM28XX_R17_BGAIN       0x17
+#define EM28XX_R18_ROFFSET     0x18
+#define EM28XX_R19_GOFFSET     0x19
+#define EM28XX_R1A_BOFFSET     0x1a
+
+#define EM28XX_R1B_OFLOW       0x1b
+#define EM28XX_R1C_HSTART      0x1c
+#define EM28XX_R1D_VSTART      0x1d
+#define EM28XX_R1E_CWIDTH      0x1e
+#define EM28XX_R1F_CHEIGHT     0x1f
+
+#define EM28XX_R20_YGAIN       0x20
+#define EM28XX_R21_YOFFSET     0x21
+#define EM28XX_R22_UVGAIN      0x22
+#define EM28XX_R23_UOFFSET     0x23
+#define EM28XX_R24_VOFFSET     0x24
+#define EM28XX_R25_SHARPNESS   0x25
+
+#define EM28XX_R26_COMPR       0x26
+#define EM28XX_R27_OUTFMT      0x27
+
+#define EM28XX_R28_XMIN        0x28
+#define EM28XX_R29_XMAX        0x29
+#define EM28XX_R2A_YMIN        0x2a
+#define EM28XX_R2B_YMAX        0x2b
+
+#define EM28XX_R30_HSCALELOW   0x30
+#define EM28XX_R31_HSCALEHIGH  0x31
+#define EM28XX_R32_VSCALELOW   0x32
+#define EM28XX_R33_VSCALEHIGH  0x33
+
+#define EM28XX_R40_AC97LSB     0x40
+#define EM28XX_R41_AC97MSB     0x41
+#define EM28XX_R42_AC97ADDR    0x42
+#define EM28XX_R43_AC97BUSY    0x43
+
+/* em202 registers */
+#define EM28XX_R02_MASTER_AC97 0x02
+#define EM28XX_R10_LINE_IN_AC97    0x10
+#define EM28XX_R14_VIDEO_AC97  0x14
+
+/* register settings */
+#define EM2800_AUDIO_SRC_TUNER  0x0d
+#define EM2800_AUDIO_SRC_LINE   0x0c
+#define EM28XX_AUDIO_SRC_TUNER 0xc0
+#define EM28XX_AUDIO_SRC_LINE  0x80
+
+/* FIXME: Need to be populated with the other chip ID's */
+enum em28xx_chip_id {
+       CHIP_ID_EM2883 = 36,
+};
index 4abe6701a7700894624b17ad7db40547248b2f67..8996175cc95075bca9c42c89501a2adc51bd12fc 100644 (file)
@@ -1,5 +1,6 @@
 /*
-   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+                   video capture devices
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
 #define em28xx_videodbg(fmt, arg...) do {\
        if (video_debug) \
                printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __FUNCTION__ , ##arg); } while (0)
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define em28xx_isocdbg(fmt, arg...) \
+do {\
+       if (isoc_debug) { \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); \
+       } \
+  } while (0)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -74,9 +87,9 @@ MODULE_PARM_DESC(video_nr, "video device numbers");
 MODULE_PARM_DESC(vbi_nr,   "vbi device numbers");
 MODULE_PARM_DESC(radio_nr, "radio device numbers");
 
-static unsigned int video_debug = 0;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
 
 /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
 static unsigned long em28xx_devused;
@@ -93,7 +106,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
                .step = 0x1,
                .default_value = 0x1f,
                .flags = 0,
-       },{
+       }, {
                .id = V4L2_CID_AUDIO_MUTE,
                .type = V4L2_CTRL_TYPE_BOOLEAN,
                .name = "Mute",
@@ -107,8 +120,391 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
 
 static struct usb_driver em28xx_usb_driver;
 
+/* ------------------------------------------------------------------
+       DMA and thread functions
+   ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct em28xx *dev,
+                                 struct em28xx_dmaqueue *dma_q,
+                                 struct em28xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
 
-/*********************  v4l2 interface  ******************************************/
+       dev->isoc_ctl.buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void em28xx_copy_video(struct em28xx *dev,
+                             struct em28xx_dmaqueue  *dma_q,
+                             struct em28xx_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       void *fieldstart, *startwrite, *startread;
+       int  linesdone, currlinedone, offset, lencopy, remain;
+       int bytesperline = dev->width << 1;
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       if (p[0] != 0x88 && p[0] != 0x22) {
+               em28xx_isocdbg("frame is not complete\n");
+               len += 4;
+       } else
+               p += 4;
+
+       startread = p;
+       remain = len;
+
+       /* Interlaces frame */
+       if (buf->top_field)
+               fieldstart = outp;
+       else
+               fieldstart = outp + bytesperline;
+
+       linesdone = dma_q->pos / bytesperline;
+       currlinedone = dma_q->pos % bytesperline;
+       offset = linesdone * bytesperline * 2 + currlinedone;
+       startwrite = fieldstart + offset;
+       lencopy = bytesperline - currlinedone;
+       lencopy = lencopy > remain ? remain : lencopy;
+
+       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+               em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
+                              ((char *)startwrite + lencopy) -
+                              ((char *)outp + buf->vb.size));
+               lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
+       }
+       if (lencopy <= 0)
+               return;
+       memcpy(startwrite, startread, lencopy);
+
+       remain -= lencopy;
+
+       while (remain > 0) {
+               startwrite += lencopy + bytesperline;
+               startread += lencopy;
+               if (bytesperline > remain)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+                       em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
+                                      ((char *)startwrite + lencopy) -
+                                      ((char *)outp + buf->vb.size));
+                       lencopy = remain = (char *)outp + buf->vb.size -
+                                          (char *)startwrite;
+               }
+               if (lencopy <= 0)
+                       break;
+
+               memcpy(startwrite, startread, lencopy);
+
+               remain -= lencopy;
+       }
+
+       dma_q->pos += len;
+}
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+       } else {
+               em28xx_isocdbg("URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+       }
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
+                                         struct em28xx_buffer **buf)
+{
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               em28xx_isocdbg("No active queue to serve\n");
+               dev->isoc_ctl.buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+
+       /* Cleans up buffer - Usefull for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0, (*buf)->vb.size);
+
+       dev->isoc_ctl.buf = *buf;
+
+       return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       struct em28xx_buffer    *buf;
+       struct em28xx_dmaqueue  *dma_q = urb->context;
+       unsigned char *outp = NULL;
+       int i, len = 0, rc = 1;
+       unsigned char *p;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       buf = dev->isoc_ctl.buf;
+       if (buf != NULL)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length - 4;
+
+               if (urb->iso_frame_desc[i].actual_length <= 0) {
+                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
+                       continue;
+               }
+               if (urb->iso_frame_desc[i].actual_length >
+                                               dev->max_pkt_size) {
+                       em28xx_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* FIXME: incomplete buffer checks where removed to make
+                  logic simpler. Impacts of those changes should be evaluated
+                */
+               if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
+                       em28xx_isocdbg("VBI HEADER!!!\n");
+                       /* FIXME: Should add vbi copy */
+                       continue;
+               }
+               if (p[0] == 0x22 && p[1] == 0x5a) {
+                       em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
+                                      len, (p[2] & 1)? "odd" : "even");
+
+                       if (!(p[2] & 1)) {
+                               if (buf != NULL)
+                                       buffer_filled(dev, dma_q, buf);
+                               get_next_buf(dma_q, &buf);
+                               if (buf == NULL)
+                                       outp = NULL;
+                               else
+                                       outp = videobuf_to_vmalloc(&buf->vb);
+                       }
+
+                       if (buf != NULL) {
+                               if (p[2] & 1)
+                                       buf->top_field = 0;
+                               else
+                                       buf->top_field = 1;
+                       }
+
+                       dma_q->pos = 0;
+               }
+               if (buf != NULL)
+                       em28xx_copy_video(dev, dma_q, buf, p, outp, len);
+       }
+       return rc;
+}
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct em28xx_fh *fh = vq->priv_data;
+       struct em28xx        *dev = fh->dev;
+       struct v4l2_frequency f;
+
+       *size = 16 * fh->dev->width * fh->dev->height >> 3;
+       if (0 == *count)
+               *count = EM28XX_DEF_BUF;
+
+       if (*count < EM28XX_MIN_BUF)
+               *count = EM28XX_MIN_BUF;
+
+       /* Ask tuner to go to analog mode */
+       memset(&f, 0, sizeof(f));
+       f.frequency = dev->ctl_freq;
+
+       em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+
+       return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx        *dev = fh->dev;
+       unsigned long flags = 0;
+       if (in_interrupt())
+               BUG();
+
+       /* We used to wait for the buffer to finish here, but this didn't work
+          because, as we were keeping the state as VIDEOBUF_QUEUED,
+          videobuf_queue_cancel marked it as finished for us.
+          (Also, it could wedge forever if the hardware was misconfigured.)
+
+          This should be safe; by the time we get here, the buffer isn't
+          queued anymore. If we ever start marking the buffers as
+          VIDEOBUF_ACTIVE, it won't be, though.
+       */
+       spin_lock_irqsave(&dev->slock, flags);
+       if (dev->isoc_ctl.buf == buf)
+               dev->isoc_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx        *dev = fh->dev;
+       int                  rc = 0, urb_init = 0;
+
+       /* FIXME: It assumes depth = 16 */
+       /* The only currently supported format is 16 bits/pixel */
+       buf->vb.size = 16 * dev->width * dev->height >> 3;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       buf->vb.width  = dev->width;
+       buf->vb.height = dev->height;
+       buf->vb.field  = field;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       if (!dev->isoc_ctl.num_bufs)
+               urb_init = 1;
+
+       if (urb_init) {
+               rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
+                                     EM28XX_NUM_BUFS, dev->max_pkt_size,
+                                     em28xx_isoc_copy);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct em28xx_buffer    *buf     = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx_fh        *fh      = vq->priv_data;
+       struct em28xx           *dev     = fh->dev;
+       struct em28xx_dmaqueue  *vidq    = &dev->vidq;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+                               struct videobuf_buffer *vb)
+{
+       struct em28xx_buffer   *buf  = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx_fh       *fh   = vq->priv_data;
+       struct em28xx          *dev  = (struct em28xx *)fh->dev;
+
+       em28xx_isocdbg("em28xx: called buffer_release\n");
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops em28xx_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/*********************  v4l2 interface  **************************************/
 
 /*
  * em28xx_config()
@@ -123,9 +519,9 @@ static int em28xx_config(struct em28xx *dev)
 
        /* enable vbi capturing */
 
-/*     em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
-/*     em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
-       em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
+/*     em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
+/*     em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
+       em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
 
        dev->mute = 1;          /* maybe not the right place... */
        dev->volume = 0x1f;
@@ -152,23 +548,6 @@ static void em28xx_config_i2c(struct em28xx *dev)
        em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 }
 
-/*
- * em28xx_empty_framequeues()
- * prepare queues for incoming and outgoing frames
- */
-static void em28xx_empty_framequeues(struct em28xx *dev)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&dev->inqueue);
-       INIT_LIST_HEAD(&dev->outqueue);
-
-       for (i = 0; i < EM28XX_NUM_FRAMES; i++) {
-               dev->frame[i].state = F_UNUSED;
-               dev->frame[i].buf.bytesused = 0;
-       }
-}
-
 static void video_mux(struct em28xx *dev, int index)
 {
        struct v4l2_routing route;
@@ -181,12 +560,15 @@ static void video_mux(struct em28xx *dev, int index)
        em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
        if (dev->has_msp34xx) {
-               if (dev->i2s_speed)
-                       em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
+               if (dev->i2s_speed) {
+                       em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
+                               &dev->i2s_speed);
+               }
                route.input = dev->ctl_ainput;
                route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
                /* Note: this is msp3400 specific */
-               em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+               em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
+                       &route);
        }
 
        em28xx_audio_analog_set(dev);
@@ -202,15 +584,12 @@ static int res_get(struct em28xx_fh *fh)
        if (fh->stream_on)
                return rc;
 
-       mutex_lock(&dev->lock);
-
        if (dev->stream_on)
-               rc = -EINVAL;
-       else {
-               dev->stream_on = 1;
-               fh->stream_on  = 1;
-       }
+               return -EINVAL;
 
+       mutex_lock(&dev->lock);
+       dev->stream_on = 1;
+       fh->stream_on  = 1;
        mutex_unlock(&dev->lock);
        return rc;
 }
@@ -230,33 +609,6 @@ static void res_free(struct em28xx_fh *fh)
        mutex_unlock(&dev->lock);
 }
 
-/*
- * em28xx_vm_open()
- */
-static void em28xx_vm_open(struct vm_area_struct *vma)
-{
-       struct em28xx_frame_t *f = vma->vm_private_data;
-       f->vma_use_count++;
-}
-
-/*
- * em28xx_vm_close()
- */
-static void em28xx_vm_close(struct vm_area_struct *vma)
-{
-       /* NOTE: buffers are not freed here */
-       struct em28xx_frame_t *f = vma->vm_private_data;
-
-       if (f->vma_use_count)
-               f->vma_use_count--;
-}
-
-static struct vm_operations_struct em28xx_vm_ops = {
-       .open = em28xx_vm_open,
-       .close = em28xx_vm_close,
-};
-
-
 /*
  * em28xx_get_ctrl()
  * return the current saturation, brightness or contrast, mute state
@@ -296,34 +648,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
        }
 }
 
-/*
- * em28xx_stream_interrupt()
- * stops streaming
- */
-static int em28xx_stream_interrupt(struct em28xx *dev)
-{
-       int rc = 0;
-
-       /* stop reading from the device */
-
-       dev->stream = STREAM_INTERRUPT;
-       rc = wait_event_timeout(dev->wait_stream,
-                               (dev->stream == STREAM_OFF) ||
-                               (dev->state & DEV_DISCONNECTED),
-                               EM28XX_URB_TIMEOUT);
-
-       if (rc) {
-               dev->state |= DEV_MISCONFIGURED;
-               em28xx_videodbg("device is misconfigured; close and "
-                       "open /dev/video%d again\n",
-                               dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
-               return rc;
-       }
-
-       return 0;
-}
-
-
 static int check_dev(struct em28xx *dev)
 {
        if (dev->state & DEV_DISCONNECTED) {
@@ -370,8 +694,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
        f->fmt.pix.width = dev->width;
        f->fmt.pix.height = dev->height;
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       f->fmt.pix.bytesperline = dev->bytesperline;
-       f->fmt.pix.sizeimage = dev->frame_size;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
@@ -447,7 +771,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       int                   rc, i;
+       int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
@@ -457,49 +781,34 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
 
        mutex_lock(&dev->lock);
 
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].vma_use_count) {
-                       em28xx_videodbg("VIDIOC_S_FMT failed. "
-                                       "Unmap the buffers first.\n");
-                       rc = -EINVAL;
-                       goto err;
-               }
-
-       /* stop io in case it is already in progress */
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0)
-                       goto err;
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               em28xx_errdev("%s queue busy\n", __func__);
+               rc = -EBUSY;
+               goto out;
        }
 
-       em28xx_release_buffers(dev);
-       dev->io = IO_NONE;
+       if (dev->stream_on && !fh->stream_on) {
+               em28xx_errdev("%s device in use by another fh\n", __func__);
+               rc = -EBUSY;
+               goto out;
+       }
 
        /* set new image size */
        dev->width = f->fmt.pix.width;
        dev->height = f->fmt.pix.height;
-       dev->frame_size = dev->width * dev->height * 2;
-       dev->field_size = dev->frame_size >> 1;
-       dev->bytesperline = dev->width * 2;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
-       /* FIXME: This is really weird! Why capture is starting with
-          this ioctl ???
-        */
-       em28xx_uninit_isoc(dev);
        em28xx_set_alternate(dev);
-       em28xx_capture_start(dev, 1);
        em28xx_resolution_set(dev);
-       em28xx_init_isoc(dev);
+
        rc = 0;
 
-err:
+out:
        mutex_unlock(&dev->lock);
        return rc;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
 {
        struct em28xx_fh   *fh  = priv;
        struct em28xx      *dev = fh->dev;
@@ -524,9 +833,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
        /* set new image size */
        dev->width = f.fmt.pix.width;
        dev->height = f.fmt.pix.height;
-       dev->frame_size = dev->width * dev->height * 2;
-       dev->field_size = dev->frame_size >> 1;
-       dev->bytesperline = dev->width * 2;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
        em28xx_resolution_set(dev);
@@ -619,11 +925,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 
        index = dev->ctl_ainput;
 
-       if (index == 0) {
+       if (index == 0)
                strcpy(a->name, "Television");
-       } else {
+       else
                strcpy(a->name, "Line In");
-       }
+
        a->capability = V4L2_AUDCAP_STEREO;
        a->index = index;
 
@@ -834,9 +1140,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int em28xx_reg_len(int reg)
 {
        switch (reg) {
-       case AC97LSB_REG:
-       case HSCALELOW_REG:
-       case VSCALELOW_REG:
+       case EM28XX_R40_AC97LSB:
+       case EM28XX_R30_HSCALELOW:
+       case EM28XX_R32_VSCALELOW:
                return 2;
        default:
                return 1;
@@ -918,23 +1224,11 @@ static int vidioc_streamon(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       if (list_empty(&dev->inqueue))
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
 
-       if (unlikely(res_get(fh) < 0)) {
-               mutex_unlock(&dev->lock);
+       if (unlikely(res_get(fh) < 0))
                return -EBUSY;
-       }
 
-       dev->stream = STREAM_ON;        /* FIXME: Start video capture here? */
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_streamon(&fh->vb_vidq));
 }
 
 static int vidioc_streamoff(struct file *file, void *priv,
@@ -948,23 +1242,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (type != fh->type)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0) {
-                       mutex_unlock(&dev->lock);
-                       return rc;
-               }
-       }
-
-       em28xx_empty_framequeues(dev);
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(fh);
 
-       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -1058,53 +1343,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       u32                   i;
        int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-               rb->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       if (dev->io == IO_READ) {
-               em28xx_videodbg("method is set to read;"
-                               " close and open the device again to"
-                               " choose the mmap I/O method\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < dev->num_frames; i++)
-               if (dev->frame[i].vma_use_count) {
-                       em28xx_videodbg("VIDIOC_REQBUFS failed; "
-                                       "previous buffers are still mapped\n");
-                       return -EINVAL;
-               }
-
-       mutex_lock(&dev->lock);
-
-       if (dev->stream == STREAM_ON) {
-               em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
-               rc = em28xx_stream_interrupt(dev);
-               if (rc < 0) {
-                       mutex_unlock(&dev->lock);
-                       return rc;
-               }
-       }
-
-       em28xx_empty_framequeues(dev);
-
-       em28xx_release_buffers(dev);
-       if (rb->count)
-               rb->count = em28xx_request_buffers(dev, rb->count);
-
-       dev->frame_current = NULL;
-       dev->io = rb->count ? IO_MMAP : IO_NONE;
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_reqbufs(&fh->vb_vidq, rb));
 }
 
 static int vidioc_querybuf(struct file *file, void *priv,
@@ -1118,52 +1363,20 @@ static int vidioc_querybuf(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-               b->index >= dev->num_frames || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
-
-       memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
-
-       if (dev->frame[b->index].vma_use_count)
-               b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       if (dev->frame[b->index].state == F_DONE)
-               b->flags |= V4L2_BUF_FLAG_DONE;
-       else if (dev->frame[b->index].state != F_UNUSED)
-               b->flags |= V4L2_BUF_FLAG_QUEUED;
-
-       mutex_unlock(&dev->lock);
-       return 0;
+       return (videobuf_querybuf(&fh->vb_vidq, b));
 }
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       unsigned long         lock_flags;
        int                   rc;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE  || dev->io != IO_MMAP ||
-                                               b->index >= dev->num_frames)
-               return -EINVAL;
-
-       if (dev->frame[b->index].state != F_UNUSED)
-               return -EAGAIN;
-
-       dev->frame[b->index].state = F_QUEUED;
-
-       /* add frame to fifo */
-       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-       list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
-       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-       return 0;
+       return (videobuf_qbuf(&fh->vb_vidq, b));
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1171,46 +1384,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
        int                   rc;
-       struct em28xx_frame_t *f;
-       unsigned long         lock_flags;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
-       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
-               return -EINVAL;
-
-       if (list_empty(&dev->outqueue)) {
-               if (dev->stream == STREAM_OFF)
-                       return -EINVAL;
-
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-
-               rc = wait_event_interruptible(dev->wait_frame,
-                                       (!list_empty(&dev->outqueue)) ||
-                                       (dev->state & DEV_DISCONNECTED));
-               if (rc)
-                       return rc;
-
-               if (dev->state & DEV_DISCONNECTED)
-                       return -ENODEV;
-       }
-
-       spin_lock_irqsave(&dev->queue_lock, lock_flags);
-       f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
-       list_del(dev->outqueue.next);
-       spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-       f->state = F_UNUSED;
-       memcpy(b, &f->buf, sizeof(*b));
+       return (videobuf_dqbuf(&fh->vb_vidq, b,
+                               file->f_flags & O_NONBLOCK));
+}
 
-       if (f->vma_use_count)
-               b->flags |= V4L2_BUF_FLAG_MAPPED;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+       struct em28xx_fh  *fh = priv;
 
-       return 0;
+       return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
 }
+#endif
+
 
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
@@ -1316,17 +1507,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
 {
        int minor = iminor(inode);
        int errCode = 0, radio = 0;
-       struct em28xx *h,*dev = NULL;
+       struct em28xx *h, *dev = NULL;
        struct em28xx_fh *fh;
+       enum v4l2_buf_type fh_type = 0;
 
        list_for_each_entry(h, &em28xx_devlist, devlist) {
                if (h->vdev->minor == minor) {
                        dev  = h;
-                       dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                }
                if (h->vbi_dev->minor == minor) {
                        dev  = h;
-                       dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+                       fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
                }
                if (h->radio_dev &&
                    h->radio_dev->minor == minor) {
@@ -1338,10 +1530,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
                return -ENODEV;
 
        em28xx_videodbg("open minor=%d type=%s users=%d\n",
-                               minor,v4l2_type_names[dev->type],dev->users);
+                               minor, v4l2_type_names[fh_type], dev->users);
 
-       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
 
+       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
        if (!fh) {
                em28xx_errdev("em28xx-video.c: Out of memory?!\n");
                return -ENOMEM;
@@ -1349,28 +1541,24 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&dev->lock);
        fh->dev = dev;
        fh->radio = radio;
+       fh->type = fh_type;
        filp->private_data = fh;
 
-       if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
                dev->width = norm_maxw(dev);
                dev->height = norm_maxh(dev);
-               dev->frame_size = dev->width * dev->height * 2;
-               dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
-               dev->bytesperline = dev->width * 2;
                dev->hscale = 0;
                dev->vscale = 0;
 
+               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
                em28xx_set_alternate(dev);
-               em28xx_capture_start(dev, 1);
                em28xx_resolution_set(dev);
 
+               /* Needed, since GPIO might have disabled power of
+                  some i2c device
+                */
+               em28xx_config_i2c(dev);
 
-               /* start the transfer */
-               errCode = em28xx_init_isoc(dev);
-               if (errCode)
-                       goto err;
-
-               em28xx_empty_framequeues(dev);
        }
        if (fh->radio) {
                em28xx_videodbg("video_open: setting radio device\n");
@@ -1379,8 +1567,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
 
        dev->users++;
 
-err:
+       videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
+                       NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+                       sizeof(struct em28xx_buffer), fh);
+
        mutex_unlock(&dev->lock);
+
        return errCode;
 }
 
@@ -1423,12 +1615,13 @@ static void em28xx_release_resources(struct em28xx *dev)
        usb_put_dev(dev->udev);
 
        /* Mark device as unused */
-       em28xx_devused&=~(1<<dev->devno);
+       em28xx_devused &= ~(1<<dev->devno);
 }
 
 /*
  * em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
  */
 static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
 {
@@ -1445,9 +1638,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
        mutex_lock(&dev->lock);
 
        if (dev->users == 1) {
-               em28xx_uninit_isoc(dev);
-               em28xx_release_buffers(dev);
-               dev->io = IO_NONE;
+               videobuf_stop(&fh->vb_vidq);
+               videobuf_mmap_free(&fh->vb_vidq);
 
                /* the device is already disconnect,
                   free the remaining resources */
@@ -1458,6 +1650,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
                        return 0;
                }
 
+               /* do this before setting alternate! */
+               em28xx_uninit_isoc(dev);
+               em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
                /* set alternate 0 */
                dev->alt = 0;
                em28xx_videodbg("setting alternate 0\n");
@@ -1479,135 +1675,29 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
  * will allocate buffers when called for the first time
  */
 static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
-                loff_t * f_pos)
+em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                loff_t *pos)
 {
-       struct em28xx_frame_t *f, *i;
-       unsigned long lock_flags;
-       int ret = 0;
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
        /* FIXME: read() is not prepared to allow changing the video
           resolution while streaming. Seems a bug at em28xx_set_fmt
         */
 
-       if (unlikely(res_get(fh) < 0))
-               return -EBUSY;
-
-       mutex_lock(&dev->lock);
-
-       if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (unlikely(res_get(fh)))
+                       return -EBUSY;
 
-       if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
-               em28xx_videodbg("not supported yet! ...\n");
-               if (copy_to_user(buf, "", 1)) {
-                       mutex_unlock(&dev->lock);
-                       return -EFAULT;
-               }
-               mutex_unlock(&dev->lock);
-               return (1);
-       }
-       if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
-               em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
-               em28xx_videodbg("not supported yet! ...\n");
-               if (copy_to_user(buf, "", 1)) {
-                       mutex_unlock(&dev->lock);
-                       return -EFAULT;
-               }
-               mutex_unlock(&dev->lock);
-               return (1);
+               return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+                                       filp->f_flags & O_NONBLOCK);
        }
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("device not present\n");
-               mutex_unlock(&dev->lock);
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg("device misconfigured; close and open it again\n");
-               mutex_unlock(&dev->lock);
-               return -EIO;
-       }
-
-       if (dev->io == IO_MMAP) {
-               em28xx_videodbg ("IO method is set to mmap; close and open"
-                               " the device again to choose the read method\n");
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       if (dev->io == IO_NONE) {
-               if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
-                       em28xx_errdev("read failed, not enough memory\n");
-                       mutex_unlock(&dev->lock);
-                       return -ENOMEM;
-               }
-               dev->io = IO_READ;
-               dev->stream = STREAM_ON;
-               em28xx_queue_unusedframes(dev);
-       }
-
-       if (!count) {
-               mutex_unlock(&dev->lock);
-               return 0;
-       }
-
-       if (list_empty(&dev->outqueue)) {
-               if (filp->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&dev->lock);
-                       return -EAGAIN;
-               }
-               ret = wait_event_interruptible
-                   (dev->wait_frame,
-                    (!list_empty(&dev->outqueue)) ||
-                    (dev->state & DEV_DISCONNECTED));
-               if (ret) {
-                       mutex_unlock(&dev->lock);
-                       return ret;
-               }
-               if (dev->state & DEV_DISCONNECTED) {
-                       mutex_unlock(&dev->lock);
-                       return -ENODEV;
-               }
-               dev->video_bytesread = 0;
-       }
-
-       f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
-
-       em28xx_queue_unusedframes(dev);
-
-       if (count > f->buf.length)
-               count = f->buf.length;
-
-       if ((dev->video_bytesread + count) > dev->frame_size)
-               count = dev->frame_size - dev->video_bytesread;
-
-       if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
-               em28xx_err("Error while copying to user\n");
-               return -EFAULT;
-       }
-       dev->video_bytesread += count;
-
-       if (dev->video_bytesread == dev->frame_size) {
-               spin_lock_irqsave(&dev->queue_lock, lock_flags);
-               list_for_each_entry(i, &dev->outqueue, frame)
-                                   i->state = F_UNUSED;
-               INIT_LIST_HEAD(&dev->outqueue);
-               spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
-               em28xx_queue_unusedframes(dev);
-               dev->video_bytesread = 0;
-       }
-
-       *f_pos += count;
-
-       mutex_unlock(&dev->lock);
-
-       return count;
+       return 0;
 }
 
 /*
@@ -1616,46 +1706,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
  */
 static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
 {
-       unsigned int mask = 0;
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
        if (unlikely(res_get(fh) < 0))
                return POLLERR;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("device not present\n");
-       } else if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg("device is misconfigured; close and open it again\n");
-       } else {
-               if (dev->io == IO_NONE) {
-                       if (!em28xx_request_buffers
-                           (dev, EM28XX_NUM_READ_FRAMES)) {
-                               em28xx_warn
-                                   ("poll() failed, not enough memory\n");
-                       } else {
-                               dev->io = IO_READ;
-                               dev->stream = STREAM_ON;
-                       }
-               }
-
-               if (dev->io == IO_READ) {
-                       em28xx_queue_unusedframes(dev);
-                       poll_wait(filp, &dev->wait_frame, wait);
-
-                       if (!list_empty(&dev->outqueue))
-                               mask |= POLLIN | POLLRDNORM;
-
-                       mutex_unlock(&dev->lock);
-
-                       return mask;
-               }
-       }
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return POLLERR;
 
-       mutex_unlock(&dev->lock);
-       return POLLERR;
+       return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
 }
 
 /*
@@ -1665,69 +1730,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct em28xx_fh *fh    = filp->private_data;
        struct em28xx    *dev   = fh->dev;
-       unsigned long    size   = vma->vm_end - vma->vm_start;
-       unsigned long    start  = vma->vm_start;
-       void             *pos;
-       u32              i;
+       int              rc;
 
        if (unlikely(res_get(fh) < 0))
                return -EBUSY;
 
-       mutex_lock(&dev->lock);
-
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_videodbg("mmap: device not present\n");
-               mutex_unlock(&dev->lock);
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_videodbg ("mmap: Device is misconfigured; close and "
-                                               "open it again\n");
-               mutex_unlock(&dev->lock);
-               return -EIO;
-       }
-
-       if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       if (size > PAGE_ALIGN(dev->frame[0].buf.length))
-               size = PAGE_ALIGN(dev->frame[0].buf.length);
-
-       for (i = 0; i < dev->num_frames; i++) {
-               if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-       if (i == dev->num_frames) {
-               em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       /* VM_IO is eventually going to replace PageReserved altogether */
-       vma->vm_flags |= VM_IO;
-       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
 
-       pos = dev->frame[i].bufmem;
-       while (size > 0) {      /* size is page-aligned */
-               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-                       em28xx_videodbg("mmap: vm_insert_page failed\n");
-                       mutex_unlock(&dev->lock);
-                       return -EAGAIN;
-               }
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
+       rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
 
-       vma->vm_ops = &em28xx_vm_ops;
-       vma->vm_private_data = &dev->frame[i];
+       em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+               rc);
 
-       em28xx_vm_open(vma);
-       mutex_unlock(&dev->lock);
-       return 0;
+       return rc;
 }
 
 static const struct file_operations em28xx_v4l_fops = {
@@ -1790,6 +1809,9 @@ static const struct video_device em28xx_video_template = {
        .vidioc_g_register          = vidioc_g_register,
        .vidioc_s_register          = vidioc_s_register,
 #endif
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       .vidiocgmbuf                = vidiocgmbuf,
+#endif
 
        .tvnorms                    = V4L2_STD_ALL,
        .current_norm               = V4L2_STD_PAL,
@@ -1818,7 +1840,7 @@ static struct video_device em28xx_radio_template = {
 #endif
 };
 
-/******************************** usb interface *****************************************/
+/******************************** usb interface ******************************/
 
 
 static LIST_HEAD(em28xx_extension_devlist);
@@ -1875,6 +1897,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
        vfd->dev = &dev->udev->dev;
        vfd->release = video_device_release;
        vfd->type = type;
+       vfd->debug = video_debug;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s",
                 dev->name, type_name);
@@ -1898,7 +1921,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
 
        dev->udev = udev;
        mutex_init(&dev->lock);
-       spin_lock_init(&dev->queue_lock);
+       spin_lock_init(&dev->slock);
        init_waitqueue_head(&dev->open);
        init_waitqueue_head(&dev->wait_frame);
        init_waitqueue_head(&dev->wait_stream);
@@ -1910,10 +1933,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->em28xx_read_reg_req = em28xx_read_reg_req;
        dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
 
-       errCode = em28xx_read_reg(dev, CHIPID_REG);
-       if (errCode >= 0)
-               em28xx_info("em28xx chip ID = %d\n", errCode);
-
        em28xx_pre_card_setup(dev);
 
        errCode = em28xx_config(dev);
@@ -1946,10 +1965,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->width = maxw;
        dev->height = maxh;
        dev->interlaced = EM28XX_INTERLACED_DEFAULT;
-       dev->field_size = dev->width * dev->height;
-       dev->frame_size =
-           dev->interlaced ? dev->field_size << 1 : dev->field_size;
-       dev->bytesperline = dev->width * 2;
        dev->hscale = 0;
        dev->vscale = 0;
        dev->ctl_input = 2;
@@ -2005,6 +2020,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
                            dev->radio_dev->minor & 0x1f);
        }
 
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+
 
        if (dev->has_msp34xx) {
                /* Send a reset to other chips via gpio */
@@ -2048,6 +2067,9 @@ static void request_module_async(struct work_struct *work)
                request_module("snd-usb-audio");
        else
                request_module("em28xx-alsa");
+
+       if (dev->has_dvb)
+               request_module("em28xx-dvb");
 }
 
 static void request_modules(struct em28xx *dev)
@@ -2077,22 +2099,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        ifnum = interface->altsetting[0].desc.bInterfaceNumber;
 
        /* Check to see next free device and mark as used */
-       nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
-       em28xx_devused|=1<<nr;
+       nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+       em28xx_devused |= 1<<nr;
 
        /* Don't register audio interfaces */
        if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
                em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
-                               udev->descriptor.idVendor,udev->descriptor.idProduct,
+                               udev->descriptor.idVendor,
+                               udev->descriptor.idProduct,
                                ifnum,
                                interface->altsetting[0].desc.bInterfaceClass);
 
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
 
        em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
-                       udev->descriptor.idVendor,udev->descriptor.idProduct,
+                       udev->descriptor.idVendor,
+                       udev->descriptor.idProduct,
                        ifnum,
                        interface->altsetting[0].desc.bInterfaceClass);
 
@@ -2102,18 +2126,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
            USB_ENDPOINT_XFER_ISOC) {
                em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
                em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENODEV;
        }
 
        if (nr >= EM28XX_MAXBOARDS) {
-               printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
-               em28xx_devused&=~(1<<nr);
+               printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+                               EM28XX_MAXBOARDS);
+               em28xx_devused &= ~(1<<nr);
                return -ENOMEM;
        }
 
@@ -2121,7 +2146,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                em28xx_err(DRIVER_NAME ": out of memory!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                return -ENOMEM;
        }
 
@@ -2145,14 +2170,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        /* compute alternate max packet sizes */
        uif = udev->actconfig->interface[0];
 
-       dev->num_alt=uif->num_altsetting;
-       em28xx_info("Alternate settings: %i\n",dev->num_alt);
-//     dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
-       dev->alt_max_pkt_size = kmalloc(32*
-                                               dev->num_alt,GFP_KERNEL);
+       dev->num_alt = uif->num_altsetting;
+       em28xx_info("Alternate settings: %i\n", dev->num_alt);
+/*     dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
+       dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
+
        if (dev->alt_max_pkt_size == NULL) {
                em28xx_errdev("out of memory!\n");
-               em28xx_devused&=~(1<<nr);
+               em28xx_devused &= ~(1<<nr);
                kfree(dev);
                return -ENOMEM;
        }
@@ -2162,11 +2187,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
                                                        wMaxPacketSize);
                dev->alt_max_pkt_size[i] =
                    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               em28xx_info("Alternate setting %i, max size= %i\n",i,
-                                                       dev->alt_max_pkt_size[i]);
+               em28xx_info("Alternate setting %i, max size= %i\n", i,
+                                               dev->alt_max_pkt_size[i]);
        }
 
-       if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
+       if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
                dev->model = card[nr];
 
        /* allocate device struct */
@@ -2202,7 +2227,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
 
        em28xx_info("disconnecting %s\n", dev->vdev->name);
 
-       /* wait until all current v4l2 io is finished then deallocate resources */
+       /* wait until all current v4l2 io is finished then deallocate
+          resources */
        mutex_lock(&dev->lock);
 
        wake_up_interruptible_all(&dev->open);
index 04e0e48ecabe54b36a6e92a70aae50623e2a8498..002f170b211a34416cdf9e414b8d7d5a7023f7f3 100644 (file)
 #define _EM28XX_H
 
 #include <linux/videodev2.h>
+#include <media/videobuf-vmalloc.h>
+
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <media/ir-kbd-i2c.h>
-
-#define UNSET -1
+#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+#include "tuner-xc2028.h"
+#include "em28xx-reg.h"
+
+/* Boards supported by driver */
+#define EM2800_BOARD_UNKNOWN                   0
+#define EM2820_BOARD_UNKNOWN                   1
+#define EM2820_BOARD_TERRATEC_CINERGY_250      2
+#define EM2820_BOARD_PINNACLE_USB_2            3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
+#define EM2820_BOARD_MSI_VOX_USB_2              5
+#define EM2800_BOARD_TERRATEC_CINERGY_200       6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
+#define EM2800_BOARD_KWORLD_USB2800             8
+#define EM2820_BOARD_PINNACLE_DVC_90           9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
+#define EM2800_BOARD_VGEAR_POCKETTV             15
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
+
+/* Limits minimum and default number of buffers */
+#define EM28XX_MIN_BUF 4
+#define EM28XX_DEF_BUF 8
 
 /* maximum number of em28xx boards */
 #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
 /* time in msecs to wait for i2c writes to finish */
 #define EM2800_I2C_WRITE_TIMEOUT 20
 
-/* the various frame states */
-enum em28xx_frame_state {
-       F_UNUSED = 0,
-       F_QUEUED,
-       F_GRABBING,
-       F_DONE,
-       F_ERROR,
+enum em28xx_mode {
+       EM28XX_MODE_UNDEFINED,
+       EM28XX_ANALOG_MODE,
+       EM28XX_DIGITAL_MODE,
 };
 
-/* stream states */
 enum em28xx_stream_state {
        STREAM_OFF,
        STREAM_INTERRUPT,
        STREAM_ON,
 };
 
-/* frames */
-struct em28xx_frame_t {
-       void *bufmem;
-       struct v4l2_buffer buf;
-       enum em28xx_frame_state state;
+struct em28xx;
+
+struct em28xx_usb_isoc_ctl {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+
+               /* Last buffer command and region */
+       u8                              cmd;
+       int                             pos, size, pktsize;
+
+               /* Last field: ODD or EVEN? */
+       int                             field;
+
+               /* Stores incomplete commands */
+       u32                             tmp_buf;
+       int                             tmp_buf_len;
+
+               /* Stores already requested buffers */
+       struct em28xx_buffer            *buf;
+
+               /* Stores the number of received fields */
+       int                             nfields;
+
+               /* isoc urb callback */
+       int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
+
+};
+
+struct em28xx_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+};
+
+/* buffer for one video frame */
+struct em28xx_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
        struct list_head frame;
-       unsigned long vma_use_count;
        int top_field;
-       int fieldbytesused;
+       int receiving;
+};
+
+struct em28xx_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+
+       wait_queue_head_t          wq;
+
+       /* Counters to control buffer fill */
+       int                        pos;
 };
 
 /* io methods */
@@ -152,6 +227,12 @@ enum em28xx_decoder {
        EM28XX_SAA7114
 };
 
+struct em28xx_reg_seq {
+       int reg;
+       unsigned char val, mask;
+       int sleep;
+};
+
 struct em28xx_board {
        char *name;
        int vchannels;
@@ -165,8 +246,7 @@ struct em28xx_board {
        unsigned int mts_firmware:1;
        unsigned int has_12mhz_i2s:1;
        unsigned int max_range_640_480:1;
-
-       unsigned int analog_gpio;
+       unsigned int has_dvb:1;
 
        enum em28xx_decoder decoder;
 
@@ -199,7 +279,10 @@ enum em28xx_dev_state {
 #define EM28XX_NUM_AUDIO_PACKETS 64
 #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
 #define EM28XX_CAPTURE_STREAM_EN 1
+
+/* em28xx extensions */
 #define EM28XX_AUDIO   0x10
+#define EM28XX_DVB     0x20
 
 struct em28xx_audio {
        char name[50];
@@ -217,13 +300,24 @@ struct em28xx_audio {
        spinlock_t slock;
 };
 
+struct em28xx;
+
+struct em28xx_fh {
+       struct em28xx *dev;
+       unsigned int  stream_on:1;      /* Locks streams */
+       int           radio;
+
+       struct videobuf_queue        vb_vidq;
+
+       enum v4l2_buf_type           type;
+};
+
 /* main device struct */
 struct em28xx {
        /* generic device properties */
        char name[30];          /* name (including minor) of the device */
        int model;              /* index in the device_data struct */
        int devno;              /* marks the number of this device */
-       unsigned int analog_gpio;
        unsigned int is_em2800:1;
        unsigned int has_msp34xx:1;
        unsigned int has_tda9887:1;
@@ -231,6 +325,16 @@ struct em28xx {
        unsigned int has_audio_class:1;
        unsigned int has_12mhz_i2s:1;
        unsigned int max_range_640_480:1;
+       unsigned int has_dvb:1;
+
+       /* Some older em28xx chips needs a waiting time after writing */
+       unsigned int wait_after_write;
+
+       /* GPIO sequences for analog and digital mode */
+       struct em28xx_reg_seq *analog_gpio, *digital_gpio;
+
+       /* GPIO sequences for tuner callbacks */
+       struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio;
 
        int video_inputs;       /* number of video inputs */
        struct list_head        devlist;
@@ -255,36 +359,28 @@ struct em28xx {
        int mute;
        int volume;
        /* frame properties */
-       struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */
-       int num_frames;         /* number of frames currently in use */
-       unsigned int frame_count;       /* total number of transfered frames */
-       struct em28xx_frame_t *frame_current;   /* the frame that is being filled */
        int width;              /* current frame width */
        int height;             /* current frame height */
-       int frame_size;         /* current frame size */
-       int field_size;         /* current field size */
-       int bytesperline;
        int hscale;             /* horizontal scale factor (see datasheet) */
        int vscale;             /* vertical scale factor (see datasheet) */
        int interlaced;         /* 1=interlace fileds, 0=just top fileds */
-       int type;
        unsigned int video_bytesread;   /* Number of bytes read */
 
        unsigned long hash;     /* eeprom hash - for boards with generic ID */
-       unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
+       unsigned long i2c_hash; /* i2c devicelist hash -
+                                  for boards with generic ID */
 
        struct em28xx_audio *adev;
 
        /* states */
        enum em28xx_dev_state state;
-       enum em28xx_stream_state stream;
        enum em28xx_io_method io;
 
        struct work_struct         request_module_wk;
 
        /* locks */
        struct mutex lock;
-       spinlock_t queue_lock;
+       /* spinlock_t queue_lock; */
        struct list_head inqueue, outqueue;
        wait_queue_head_t open, wait_frame, wait_stream;
        struct video_device *vbi_dev;
@@ -292,6 +388,11 @@ struct em28xx {
 
        unsigned char eedata[256];
 
+       /* Isoc control struct */
+       struct em28xx_dmaqueue vidq;
+       struct em28xx_usb_isoc_ctl isoc_ctl;
+       spinlock_t slock;
+
        /* usb transfer */
        struct usb_device *udev;        /* the usb device */
        int alt;                /* alternate */
@@ -301,20 +402,21 @@ struct em28xx {
        struct urb *urb[EM28XX_NUM_BUFS];       /* urb for isoc transfers */
        char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
        /* helper funcs that call usb_control_msg */
-       int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf,
-                                 int len);
-       int (*em28xx_read_reg) (struct em28xx * dev, u16 reg);
-       int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg,
+       int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
                                        char *buf, int len);
-       int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg,
+       int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+       int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+                                       char *buf, int len);
+       int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
                                      char *buf, int len);
-       int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
-};
+       int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
 
-struct em28xx_fh {
-       struct em28xx *dev;
-       unsigned int  stream_on:1;      /* Locks streams */
-       int           radio;
+       enum em28xx_mode mode;
+
+       /* Caches GPO and GPIO registers */
+       unsigned char   reg_gpo, reg_gpio;
+
+       struct em28xx_dvb *dvb;
 };
 
 struct em28xx_ops {
@@ -351,22 +453,27 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
 int em28xx_capture_start(struct em28xx *dev, int start);
 int em28xx_outfmt_set_yuv422(struct em28xx *dev);
 int em28xx_resolution_set(struct em28xx *dev);
-int em28xx_init_isoc(struct em28xx *dev);
-void em28xx_uninit_isoc(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
+void em28xx_uninit_isoc(struct em28xx *dev);
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 
 /* Provided by em28xx-video.c */
 int em28xx_register_extension(struct em28xx_ops *dev);
 void em28xx_unregister_extension(struct em28xx_ops *dev);
 
 /* Provided by em28xx-cards.c */
-extern int em2800_variant_detect(struct usb_device* udev,int model);
+extern int em2800_variant_detect(struct usb_device *udev, int model);
 extern void em28xx_pre_card_setup(struct em28xx *dev);
 extern void em28xx_card_setup(struct em28xx *dev);
 extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
 extern const unsigned int em28xx_bcount;
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
+int em28xx_tuner_callback(void *ptr, int command, int arg);
 
 /* Provided by em28xx-input.c */
 /* TODO: Check if the standard get_key handlers on ir-common can be used */
@@ -375,71 +482,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
                                     u32 *ir_raw);
 
-/* em2800 registers */
-#define EM2800_AUDIOSRC_REG 0x08
-
-/* em28xx registers */
-#define I2C_CLK_REG    0x06
-#define CHIPID_REG     0x0a
-#define USBSUSP_REG    0x0c    /* */
-
-#define AUDIOSRC_REG   0x0e
-#define XCLK_REG       0x0f
-
-#define VINMODE_REG    0x10
-#define VINCTRL_REG    0x11
-#define VINENABLE_REG  0x12    /* */
-
-#define GAMMA_REG      0x14
-#define RGAIN_REG      0x15
-#define GGAIN_REG      0x16
-#define BGAIN_REG      0x17
-#define ROFFSET_REG    0x18
-#define GOFFSET_REG    0x19
-#define BOFFSET_REG    0x1a
-
-#define OFLOW_REG      0x1b
-#define HSTART_REG     0x1c
-#define VSTART_REG     0x1d
-#define CWIDTH_REG     0x1e
-#define CHEIGHT_REG    0x1f
-
-#define YGAIN_REG      0x20
-#define YOFFSET_REG    0x21
-#define UVGAIN_REG     0x22
-#define UOFFSET_REG    0x23
-#define VOFFSET_REG    0x24
-#define SHARPNESS_REG  0x25
-
-#define COMPR_REG      0x26
-#define OUTFMT_REG     0x27
-
-#define XMIN_REG       0x28
-#define XMAX_REG       0x29
-#define YMIN_REG       0x2a
-#define YMAX_REG       0x2b
-
-#define HSCALELOW_REG  0x30
-#define HSCALEHIGH_REG 0x31
-#define VSCALELOW_REG  0x32
-#define VSCALEHIGH_REG 0x33
-
-#define AC97LSB_REG    0x40
-#define AC97MSB_REG    0x41
-#define AC97ADDR_REG   0x42
-#define AC97BUSY_REG   0x43
-
-/* em202 registers */
-#define MASTER_AC97    0x02
-#define LINE_IN_AC97    0x10
-#define VIDEO_AC97     0x14
-
-/* register settings */
-#define EM2800_AUDIO_SRC_TUNER  0x0d
-#define EM2800_AUDIO_SRC_LINE   0x0c
-#define EM28XX_AUDIO_SRC_TUNER 0xc0
-#define EM28XX_AUDIO_SRC_LINE  0x80
-
 /* printk macros */
 
 #define em28xx_err(fmt, arg...) do {\
@@ -456,80 +498,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
        printk(KERN_WARNING "%s: "fmt,\
                        dev->name , ##arg); } while (0)
 
-inline static int em28xx_compression_disable(struct em28xx *dev)
+static inline int em28xx_compression_disable(struct em28xx *dev)
 {
        /* side effect of disabling scaler and mixer */
-       return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
+       return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1);
 }
 
-inline static int em28xx_contrast_get(struct em28xx *dev)
+static inline int em28xx_contrast_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
+       return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
 }
 
-inline static int em28xx_brightness_get(struct em28xx *dev)
+static inline int em28xx_brightness_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, YOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
 }
 
-inline static int em28xx_saturation_get(struct em28xx *dev)
+static inline int em28xx_saturation_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
+       return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
 }
 
-inline static int em28xx_u_balance_get(struct em28xx *dev)
+static inline int em28xx_u_balance_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, UOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
 }
 
-inline static int em28xx_v_balance_get(struct em28xx *dev)
+static inline int em28xx_v_balance_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, VOFFSET_REG);
+       return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
 }
 
-inline static int em28xx_gamma_get(struct em28xx *dev)
+static inline int em28xx_gamma_get(struct em28xx *dev)
 {
-       return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
+       return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
 }
 
-inline static int em28xx_contrast_set(struct em28xx *dev, s32 val)
+static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
 }
 
-inline static int em28xx_brightness_set(struct em28xx *dev, s32 val)
+static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_saturation_set(struct em28xx *dev, s32 val)
+static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
 }
 
-inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
 }
 
-inline static int em28xx_gamma_set(struct em28xx *dev, s32 val)
+static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
 {
        u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
+       return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
 }
 
 /*FIXME: maxw should be dependent of alt mode */
-inline static unsigned int norm_maxw(struct em28xx *dev)
+static inline unsigned int norm_maxw(struct em28xx *dev)
 {
        if (dev->max_range_640_480)
                return 640;
@@ -537,7 +579,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev)
                return 720;
 }
 
-inline static unsigned int norm_maxh(struct em28xx *dev)
+static inline unsigned int norm_maxh(struct em28xx *dev)
 {
        if (dev->max_range_640_480)
                return 480;
index 02c741d8f85a55a7e2b965922610c7b4ae09733c..cc77d144df3cc4bc68f77c9fc7a07a150db7b2ac 100644 (file)
@@ -199,7 +199,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-                                __FILE__, __FUNCTION__, __LINE__ , ## args); \
+                                __FILE__, __func__, __LINE__ , ## args); \
        }                                                                     \
 } while (0)
 #      define KDBG(level, fmt, args...)                                      \
@@ -209,7 +209,7 @@ do {                                                                          \
                        pr_info("et61x251: " fmt "\n", ## args);              \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -225,7 +225,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index 06b6a3ae06c4c151bb8d54c04299920e11449e7a..5e749c528a624e7ea6babc290ede9dc041726e88 100644 (file)
@@ -2523,7 +2523,9 @@ static const struct file_operations et61x251_fops = {
        .open =    et61x251_open,
        .release = et61x251_release,
        .ioctl =   et61x251_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
@@ -2538,7 +2540,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct et61x251_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0;
 
index c7fed340565524d8ad13553e7fce99ed84c56c37..352f84d440fb64272e6818fc2439122fa0c43230 100644 (file)
 
 #include <media/saa7146_vv.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
 /* global variables */
-static int hexium_num = 0;
+static int hexium_num;
 
 #define HEXIUM_GEMINI                  4
 #define HEXIUM_GEMINI_DUAL             5
index 137c4736da04085ccf8d3df188d905ea97ceda43..8d3c1482e7ea376b5ae9919f7107b7eded09e185 100644 (file)
 
 #include <media/saa7146_vv.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug verbosity");
 
 /* global variables */
-static int hexium_num = 0;
+static int hexium_num;
 
 #define HEXIUM_HV_PCI6_ORION           1
 #define HEXIUM_ORION_1SVHS_3BNC                2
index dabafdf71e609ca2860b55ac449d3989154f8bd3..11c5fdedc23bc341fb82ab4459d42b53bcab9a5f 100644 (file)
@@ -50,7 +50,7 @@
 static int debug;
 module_param(debug, int, 0644);    /* debug level (0,1,2) */
 
-static int hauppauge = 0;
+static int hauppauge;
 module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
 MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
 
@@ -153,7 +153,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        }
 
        if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
-               dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
+               dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
                        buf[0], buf[1], buf[2], buf[3]);
 
        /* no key pressed or signal from other ir remote */
@@ -508,10 +508,10 @@ static int ir_probe(struct i2c_adapter *adap)
        static const int probe_em28XX[] = { 0x30, 0x47, -1 };
        static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
        static const int probe_cx23885[] = { 0x6b, -1 };
-       const int *probe = NULL;
-       struct i2c_client c;
+       const int *probe;
+       struct i2c_client *c;
        unsigned char buf;
-       int i,rc;
+       int i, rc;
 
        switch (adap->id) {
        case I2C_HW_B_BT848:
@@ -532,23 +532,27 @@ static int ir_probe(struct i2c_adapter *adap)
        case I2C_HW_B_CX23885:
                probe = probe_cx23885;
                break;
-       }
-       if (NULL == probe)
+       default:
                return 0;
+       }
+
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return -ENOMEM;
 
-       memset(&c,0,sizeof(c));
-       c.adapter = adap;
+       c->adapter = adap;
        for (i = 0; -1 != probe[i]; i++) {
-               c.addr = probe[i];
-               rc = i2c_master_recv(&c,&buf,0);
+               c->addr = probe[i];
+               rc = i2c_master_recv(c, &buf, 0);
                dprintk(1,"probe 0x%02x @ %s: %s\n",
                        probe[i], adap->name,
                        (0 == rc) ? "yes" : "no");
                if (0 == rc) {
-                       ir_attach(adap,probe[i],0,0);
+                       ir_attach(adap, probe[i], 0, 0);
                        break;
                }
        }
+       kfree(c);
        return 0;
 }
 
index 270906fc314600107e161dde9575308c85385f1e..b6171702c4d051824c5215f5b93b9ca8f339cbc2 100644 (file)
@@ -10,6 +10,7 @@ config VIDEO_IVTV
        select VIDEO_CX25840
        select VIDEO_MSP3400
        select VIDEO_SAA711X
+       select VIDEO_SAA717X
        select VIDEO_SAA7127
        select VIDEO_TVAUDIO
        select VIDEO_CS53L32A
index f23c6b8d6911dee0f360c60e5c745b869df95e6e..e908649ea37cc738fc2611fb4cb14cbfe3a90ea0 100644 (file)
@@ -416,11 +416,10 @@ static const struct ivtv_card ivtv_card_avc2410 = {
           on the country/region setting of the user to decide which tuner
           is available. */
        .tuners = {
-               /* This tuner has been verified for the AVC2410 */
                { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-               /* This is a good guess, but I'm not totally sure this is
-                  the correct tuner for NTSC. */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
+                       .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_avc2410,
        .i2c = &ivtv_i2c_std,
index 191aafdd9968fd008fbc405a2b566a03cf1ab452..9186fa2ee5fc01bff46a451df77569cbe593eba6 100644 (file)
 
 #define IVTV_CARD_MAX_VIDEO_INPUTS 6
 #define IVTV_CARD_MAX_AUDIO_INPUTS 3
-#define IVTV_CARD_MAX_TUNERS      2
+#define IVTV_CARD_MAX_TUNERS      3
 
 /* SAA71XX HW inputs */
 #define IVTV_SAA71XX_COMPOSITE0 0
index 948ca35e7ee897469eafd905c0ffb4432dd4fc76..065df53f80fdcbf543486a9c1fb5ce739e440841 100644 (file)
@@ -101,7 +101,7 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
 static unsigned int cardtype_c = 1;
 static unsigned int tuner_c = 1;
 static unsigned int radio_c = 1;
-static char pal[] = "--";
+static char pal[] = "---";
 static char secam[] = "--";
 static char ntsc[] = "-";
 
@@ -126,12 +126,13 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS;
 static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS;
 static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS;
 
-static int ivtv_yuv_mode = 0;
-static int ivtv_yuv_threshold=-1;
+static int ivtv_yuv_mode;
+static int ivtv_yuv_threshold = -1;
 static int ivtv_pci_latency = 1;
 
-int ivtv_debug = 0;
+int ivtv_debug;
 
+static int tunertype = -1;
 static int newi2c = -1;
 
 module_param_array(tuner, int, &tuner_c, 0644);
@@ -154,6 +155,7 @@ module_param(dec_mpg_buffers, int, 0644);
 module_param(dec_yuv_buffers, int, 0644);
 module_param(dec_vbi_buffers, int, 0644);
 
+module_param(tunertype, int, 0644);
 module_param(newi2c, int, 0644);
 
 MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
@@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype,
                 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
                 "\t\t\t 0 = Autodetect (default)\n"
                 "\t\t\t-1 = Ignore this card\n\t\t");
-MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
-MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
-MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
+MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
+MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)");
+MODULE_PARM_DESC(tunertype,
+               "Specify tuner type:\n"
+               "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n"
+               "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n"
+               "\t\t\t-1 = Autodetect (default)\n");
 MODULE_PARM_DESC(debug,
                 "Debug level (bitmask). Default: 0\n"
                 "\t\t\t   1/0x0001: warning\n"
@@ -490,30 +497,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
 {
        switch (pal[0]) {
                case '6':
+                       tunertype = 0;
                        return V4L2_STD_PAL_60;
                case 'b':
                case 'B':
                case 'g':
                case 'G':
-                       return V4L2_STD_PAL_BG;
                case 'h':
                case 'H':
-                       return V4L2_STD_PAL_H;
+                       tunertype = 0;
+                       return V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
                case 'n':
                case 'N':
+                       tunertype = 1;
                        if (pal[1] == 'c' || pal[1] == 'C')
                                return V4L2_STD_PAL_Nc;
                        return V4L2_STD_PAL_N;
                case 'i':
                case 'I':
+                       tunertype = 0;
                        return V4L2_STD_PAL_I;
                case 'd':
                case 'D':
                case 'k':
                case 'K':
+                       tunertype = 0;
                        return V4L2_STD_PAL_DK;
                case 'M':
                case 'm':
+                       tunertype = 1;
                        return V4L2_STD_PAL_M;
                case '-':
                        break;
@@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
                case 'G':
                case 'h':
                case 'H':
+                       tunertype = 0;
                        return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
                case 'd':
                case 'D':
                case 'k':
                case 'K':
+                       tunertype = 0;
                        return V4L2_STD_SECAM_DK;
                case 'l':
                case 'L':
+                       tunertype = 0;
                        if (secam[1] == 'C' || secam[1] == 'c')
                                return V4L2_STD_SECAM_LC;
                        return V4L2_STD_SECAM_L;
@@ -550,12 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
        switch (ntsc[0]) {
                case 'm':
                case 'M':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M;
                case 'j':
                case 'J':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M_JP;
                case 'k':
                case 'K':
+                       tunertype = 1;
                        return V4L2_STD_NTSC_M_KR;
                case '-':
                        break;
@@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv)
        itv->options.tuner = tuner[itv->num];
        itv->options.radio = radio[itv->num];
        itv->options.newi2c = newi2c;
-
+       if (tunertype < -1 || tunertype > 1) {
+               IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
+               tunertype = -1;
+       }
        itv->std = ivtv_parse_std(itv);
+       if (itv->std == 0 && tunertype >= 0)
+               itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
        itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15);
        chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
        if (itv->options.cardtype == -1) {
@@ -711,6 +734,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
        itv->yuv_info.lace_mode = ivtv_yuv_mode;
        itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
        itv->yuv_info.max_frames_buffered = 3;
+       itv->yuv_info.track_osd = 1;
        return 0;
 }
 
@@ -859,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
 #ifndef CONFIG_VIDEO_SAA7127
        hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
 #endif
+#ifndef CONFIG_VIDEO_SAA717X
        hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
+#endif
 #ifndef CONFIG_VIDEO_UPD64031A
        hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
 #endif
index 536140f0c19efb6eabd9f8673857c742a3a7a600..ba06e813c58c3d789222aca798e5bc6811c6caa4 100644 (file)
@@ -456,6 +456,8 @@ struct yuv_playback_info
        int v_filter_2;
        int h_filter;
 
+       u8 track_osd; /* Should yuv output track the OSD size & position */
+
        u32 osd_x_offset;
        u32 osd_y_offset;
 
index 6fb96f19a8661dfe369f7303e6ed4e11301d3ad9..a7640c49f1d84aa6f89e8f81e67b291d62a67350 100644 (file)
@@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
                        /* Process pending program info updates and pending VBI data */
                        ivtv_update_pgm_info(itv);
 
-                       if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
+                       if (time_after(jiffies,
+                                      itv->dualwatch_jiffies +
+                                      msecs_to_jiffies(1000))) {
                                itv->dualwatch_jiffies = jiffies;
                                ivtv_dualwatch(itv);
                        }
@@ -753,7 +755,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        IVTV_DEBUG_HI_FILE("Encoder poll\n");
        poll_wait(filp, &s->waitq, wait);
 
-       if (eof || s->q_full.length)
+       if (eof || s->q_full.length || s->q_io.length)
                return POLLIN | POLLRDNORM;
        return 0;
 }
index fa5ab1eb180005049db0412df19b8279303b7aec..9824eafee02131eb88b67045de9ce32de8f0e93e 100644 (file)
@@ -177,10 +177,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
        }
 
        if (id != I2C_DRIVERID_TUNER) {
-               c = i2c_new_device(&itv->i2c_adap, &info);
-               if (c->driver == NULL)
+               if (id == I2C_DRIVERID_UPD64031A ||
+                   id == I2C_DRIVERID_UPD64083) {
+                       unsigned short addrs[2] = { info.addr, I2C_CLIENT_END };
+
+                       c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs);
+               } else
+                       c = i2c_new_device(&itv->i2c_adap, &info);
+               if (c && c->driver == NULL)
                        i2c_unregister_device(c);
-               else
+               else if (c)
                        itv->i2c_clients[i] = c;
                return itv->i2c_clients[i] ? 0 : -ENODEV;
        }
index edef2a579617e722c5357b93775f88620faff327..15cac1812122e22c11805e3fe006c5111f2581ae 100644 (file)
@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
 int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
 {
        struct ivtv_open_id *id = NULL;
+       struct yuv_playback_info *yi = &itv->yuv_info;
        u32 data[CX2341X_MBOX_MAX_DATA];
        int streamtype = 0;
 
@@ -741,7 +742,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
 
                memset(vcap, 0, sizeof(*vcap));
                strcpy(vcap->driver, IVTV_DRIVER_NAME);     /* driver name */
-               strcpy(vcap->card, itv->card_name);         /* card type */
+               strncpy(vcap->card, itv->card_name,
+                               sizeof(vcap->card)-1);      /* card type */
                strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
                vcap->version = IVTV_DRIVER_VERSION;        /* version */
                vcap->capabilities = itv->v4l2_cap;         /* capabilities */
@@ -827,8 +829,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
        case VIDIOC_CROPCAP: {
                struct v4l2_cropcap *cropcap = arg;
 
-               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-                   cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
                        return -EINVAL;
                cropcap->bounds.top = cropcap->bounds.left = 0;
                cropcap->bounds.width = 720;
@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
                        cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
                } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                       cropcap->bounds.width = itv->yuv_info.osd_full_w;
-                       cropcap->bounds.height = itv->yuv_info.osd_full_h;
+                       if (yi->track_osd) {
+                               cropcap->bounds.width = yi->osd_full_w;
+                               cropcap->bounds.height = yi->osd_full_h;
+                       } else {
+                               cropcap->bounds.width = 720;
+                               cropcap->bounds.height =
+                                               itv->is_out_50hz ? 576 : 480;
+                       }
                        cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
                        cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
                } else {
@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
                        if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                               itv->yuv_info.main_rect = crop->c;
+                               yi->main_rect = crop->c;
                                return 0;
                        } else {
                                if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
@@ -867,9 +874,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        }
                        return -EINVAL;
                }
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
+               return -EINVAL;
        }
 
        case VIDIOC_G_CROP: {
@@ -878,14 +883,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
                        if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
-                               crop->c = itv->yuv_info.main_rect;
+                               crop->c = yi->main_rect;
                        else
                                crop->c = itv->main_rect;
                        return 0;
                }
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
+               return -EINVAL;
        }
 
        case VIDIOC_ENUM_FMT: {
@@ -1070,11 +1073,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        itv->main_rect.height = itv->params.height;
                        ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
                                720, itv->main_rect.height, 0, 0);
-                       itv->yuv_info.main_rect = itv->main_rect;
+                       yi->main_rect = itv->main_rect;
                        if (!itv->osd_info) {
-                               itv->yuv_info.osd_full_w = 720;
-                               itv->yuv_info.osd_full_h =
-                                               itv->is_out_50hz ? 576 : 480;
+                               yi->osd_full_w = 720;
+                               yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
                        }
                }
                break;
@@ -1272,6 +1274,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        else
                                fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
                }
+               if (yi->track_osd)
+                       fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
                break;
        }
 
@@ -1285,6 +1289,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                        (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
                itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
                ivtv_set_osd_alpha(itv);
+               yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
                break;
        }
 
@@ -1628,6 +1633,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_debug_ioctls(filp, cmd, arg);
 
@@ -1671,6 +1677,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
 
@@ -1684,6 +1691,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
                if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
                        printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
                        v4l_printk_ioctl(cmd);
+                       printk("\n");
                }
                return ivtv_control_ioctls(itv, cmd, arg);
 
index 65604dde972614cfb9c1926c3dcd89649cacc2cf..a329c4689dbf71de5b56a307c3256b6d8979aa76 100644 (file)
@@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
@@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       add_timer(&itv->dma_timer);
 }
 
 /* start the encoder DMA */
@@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
                ivtv_dma_enc_start_xfer(s);
                set_bit(IVTV_F_I_DMA, &itv->i_flags);
                itv->cur_dma_stream = s->type;
-               itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-               add_timer(&itv->dma_timer);
        }
 }
 
@@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
        ivtv_dma_dec_start_xfer(s);
        set_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = s->type;
-       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_irq_dma_read(struct ivtv *itv)
@@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
        int hw_stream_type = 0;
 
        IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
-       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
                return;
-       }
 
        if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
                s = &itv->streams[itv->cur_dma_stream];
@@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
                }
                wake_up(&s->waitq);
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
@@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
 
        ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
        IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
-       if (itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (itv->cur_dma_stream < 0)
                return;
-       }
+
        s = &itv->streams[itv->cur_dma_stream];
        ivtv_stream_sync_for_cpu(s);
 
@@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
                ivtv_dma_enc_start_xfer(s);
                return;
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
        dma_post(s);
index 13a6c374d2dbf0833108ff3e0367cbcca7e40f8e..1b5c0ac09a8552cb0c71db7a31fed5cb2a4124ef 100644 (file)
@@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
 
                /* Sleep before a retry, if not atomic */
                if (!(flags & API_NO_WAIT_MB)) {
-                       if (jiffies - then > msecs_to_jiffies(10*retries))
+                       if (time_after(jiffies,
+                                      then + msecs_to_jiffies(10*retries)))
                               break;
                        ivtv_msleep_timeout(10, 0);
                }
@@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
           data, then just return 0 as there is no need to issue this command again.
           Just an optimization to prevent unnecessary use of mailboxes. */
        if (itv->api_cache[cmd].last_jiffies &&
-           jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) &&
+           time_before(jiffies,
+                       itv->api_cache[cmd].last_jiffies +
+                       msecs_to_jiffies(1800000)) &&
            !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
                itv->api_cache[cmd].last_jiffies = jiffies;
                return 0;
@@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
                }
        }
        while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
-               if (jiffies - then > api_timeout) {
+               if (time_after(jiffies, then + api_timeout)) {
                        IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
                        /* reset the mailbox, but it is likely too late already */
                        write_sync(0, &mbox->flags);
@@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
                else
                        ivtv_msleep_timeout(1, 0);
        }
-       if (jiffies - then > msecs_to_jiffies(100))
+       if (time_after(jiffies, then + msecs_to_jiffies(100)))
                IVTV_DEBUG_WARN("%s took %u jiffies\n",
                                api_info[cmd].name,
                                jiffies_to_msecs(jiffies - then));
index 39a216713244eecd6481d75d307e0ec38f9d74b1..3e1deec67a5e33d8f12ba141546946eec6db4436 100644 (file)
@@ -51,7 +51,7 @@ void ivtv_queue_init(struct ivtv_queue *q)
 
 void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
 {
-       unsigned long flags = 0;
+       unsigned long flags;
 
        /* clear the buffer if it is going to be enqueued to the free queue */
        if (q == &s->q_free) {
@@ -71,7 +71,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu
 struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
 {
        struct ivtv_buffer *buf = NULL;
-       unsigned long flags = 0;
+       unsigned long flags;
 
        spin_lock_irqsave(&s->qlock, flags);
        if (!list_empty(&q->list)) {
index 24d98ecf35ad13de77f4d2457de6c8ba09c9c584..4ab8d36831ba427e477e984b457d967824493443 100644 (file)
@@ -768,7 +768,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
 
                        /* wait 2s for EOS interrupt */
                        while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
-                               jiffies < then + msecs_to_jiffies (2000)) {
+                               time_before(jiffies,
+                                           then + msecs_to_jiffies(2000))) {
                                schedule_timeout(msecs_to_jiffies(10));
                        }
 
index 85183480a2259e610aaad59e4341dd4d91d4d5c4..393d917cd67265367aa0280395bf521b4a57902e 100644 (file)
@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
                f->src_w -= (osd_scale * osd_crop) >> 16;
        }
 
-       /* The OSD can be moved. Track to it */
-       f->dst_x += itv->yuv_info.osd_x_offset;
-       f->dst_y += itv->yuv_info.osd_y_offset;
+       if (itv->yuv_info.track_osd) {
+               /* The OSD can be moved. Track to it */
+               f->dst_x += itv->yuv_info.osd_x_offset;
+               f->dst_y += itv->yuv_info.osd_y_offset;
+       }
 
        /* Width & height for both src & dst must be even.
           Same for coordinates. */
@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv)
        IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
        f = yi->new_frame_info[frame];
 
-       /* Update the osd pan info */
-       f.pan_x = yi->osd_x_pan;
-       f.pan_y = yi->osd_y_pan;
-       f.vis_w = yi->osd_vis_w;
-       f.vis_h = yi->osd_vis_h;
+       if (yi->track_osd) {
+               /* Snapshot the osd pan info */
+               f.pan_x = yi->osd_x_pan;
+               f.pan_y = yi->osd_y_pan;
+               f.vis_w = yi->osd_vis_w;
+               f.vis_h = yi->osd_vis_h;
+       } else {
+               /* Not tracking the osd, so assume full screen */
+               f.pan_x = 0;
+               f.pan_y = 0;
+               f.vis_w = 720;
+               f.vis_h = yi->decode_height;
+       }
 
        /* Calculate the display window coordinates. Exit if nothing left */
        if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
@@ -914,7 +924,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
 }
 
 /* Get next available yuv buffer on PVR350 */
-void ivtv_yuv_next_free(struct ivtv *itv)
+static void ivtv_yuv_next_free(struct ivtv *itv)
 {
        int draw, display;
        struct yuv_playback_info *yi = &itv->yuv_info;
@@ -937,7 +947,7 @@ void ivtv_yuv_next_free(struct ivtv *itv)
 }
 
 /* Set up frame according to ivtv_dma_frame parameters */
-void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
        struct yuv_playback_info *yi = &itv->yuv_info;
        u8 frame = yi->draw_frame;
@@ -965,12 +975,6 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
        /* Are we going to offset the Y plane */
        nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
 
-       /* Snapshot the osd pan info */
-       nf->pan_x = yi->osd_x_pan;
-       nf->pan_y = yi->osd_y_pan;
-       nf->vis_w = yi->osd_vis_w;
-       nf->vis_h = yi->osd_vis_h;
-
        nf->update = 0;
        nf->interlaced_y = 0;
        nf->interlaced_uv = 0;
@@ -1042,7 +1046,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv)
                        (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
 }
 
-int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
        DEFINE_WAIT(wait);
        int rc = 0;
index 3d51fa0a52b6132c6b09859c691c466e97e0964e..e7ccbc895d7abe4fc37b84ae805d6d504d37dbde 100644 (file)
 #include <linux/meye.h>
 
 MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
-MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera");
+MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEYE_DRIVER_VERSION);
 
-/* force usage of V4L1 API */
-static int forcev4l1; /* = 0 */
-module_param(forcev4l1, int, 0644);
-MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2");
-
 /* number of grab buffers */
 static unsigned int gbuffers = 2;
 module_param(gbuffers, int, 0444);
@@ -789,7 +784,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id)
 {
        u32 v;
        int reqnr;
-       static int sequence = 0;
+       static int sequence;
 
        v = mchip_read(MCHIP_MM_INTA);
 
@@ -876,795 +871,735 @@ static int meye_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int meye_do_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, void *arg)
+static int meyeioc_g_params(struct meye_params *p)
 {
-       switch (cmd) {
+       *p = meye.params;
+       return 0;
+}
 
-       case VIDIOCGCAP: {
-               struct video_capability *b = arg;
-               strcpy(b->name,meye.video_dev->name);
-               b->type = VID_TYPE_CAPTURE;
-               b->channels = 1;
-               b->audios = 0;
-               b->maxwidth = 640;
-               b->maxheight = 480;
-               b->minwidth = 320;
-               b->minheight = 240;
-               break;
-       }
+static int meyeioc_s_params(struct meye_params *jp)
+{
+       if (jp->subsample > 1)
+               return -EINVAL;
 
-       case VIDIOCGCHAN: {
-               struct video_channel *v = arg;
-               v->flags = 0;
-               v->tuners = 0;
-               v->type = VIDEO_TYPE_CAMERA;
-               if (v->channel != 0)
-                       return -EINVAL;
-               strcpy(v->name,"Camera");
-               break;
-       }
+       if (jp->quality > 10)
+               return -EINVAL;
 
-       case VIDIOCSCHAN: {
-               struct video_channel *v = arg;
-               if (v->channel != 0)
-                       return -EINVAL;
-               break;
-       }
+       if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+               return -EINVAL;
 
-       case VIDIOCGPICT: {
-               struct video_picture *p = arg;
-               *p = meye.picture;
-               break;
-       }
+       if (jp->framerate > 31)
+               return -EINVAL;
 
-       case VIDIOCSPICT: {
-               struct video_picture *p = arg;
-               if (p->depth != 16)
-                       return -EINVAL;
-               if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
-                                     p->brightness >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
-                                     p->hue >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
-                                     p->colour >> 10);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
-                                     p->contrast >> 10);
-               meye.picture = *p;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mutex_lock(&meye.lock);
 
-       case VIDIOCSYNC: {
-               int *i = arg;
-               int unused;
+       if (meye.params.subsample != jp->subsample ||
+           meye.params.quality != jp->quality)
+               mchip_hic_stop();       /* need restart */
+
+       meye.params = *jp;
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+                             meye.params.sharpness);
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+                             meye.params.agc);
+       sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+                             meye.params.picture);
+       mutex_unlock(&meye.lock);
 
-               if (*i < 0 || *i >= gbuffers)
-                       return -EINVAL;
+       return 0;
+}
 
-               mutex_lock(&meye.lock);
+static int meyeioc_qbuf_capt(int *nb)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
 
-               switch (meye.grab_buffer[*i].state) {
+       if (*nb >= gbuffers)
+               return -EINVAL;
 
-               case MEYE_BUF_UNUSED:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               case MEYE_BUF_USING:
-                       if (file->f_flags & O_NONBLOCK) {
-                               mutex_unlock(&meye.lock);
-                               return -EAGAIN;
-                       }
-                       if (wait_event_interruptible(meye.proc_list,
-                                                    (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
-                               mutex_unlock(&meye.lock);
-                               return -EINTR;
-                       }
-                       /* fall through */
-               case MEYE_BUF_DONE:
-                       meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
-                       kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
-               }
-               mutex_unlock(&meye.lock);
-               break;
+       if (*nb < 0) {
+               /* stop capture */
+               mchip_hic_stop();
+               return 0;
        }
 
-       case VIDIOCMCAPTURE: {
-               struct video_mmap *vm = arg;
-               int restart = 0;
-
-               if (vm->frame >= gbuffers || vm->frame < 0)
-                       return -EINVAL;
-               if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
-                       return -EINVAL;
-               if (vm->height * vm->width * 2 > gbufsize)
-                       return -EINVAL;
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-
-               mutex_lock(&meye.lock);
-               if (vm->width == 640 && vm->height == 480) {
-                       if (meye.params.subsample) {
-                               meye.params.subsample = 0;
-                               restart = 1;
-                       }
-               } else if (vm->width == 320 && vm->height == 240) {
-                       if (!meye.params.subsample) {
-                               meye.params.subsample = 1;
-                               restart = 1;
-                       }
-               } else {
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
+       if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
 
-               if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
-                       mchip_continuous_start();
-               meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mutex_lock(&meye.lock);
 
-       case VIDIOCGMBUF: {
-               struct video_mbuf *vm = arg;
-               int i;
+       if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+               mchip_cont_compression_start();
 
-               memset(vm, 0 , sizeof(*vm));
-               vm->size = gbufsize * gbuffers;
-               vm->frames = gbuffers;
-               for (i = 0; i < gbuffers; i++)
-                       vm->offsets[i] = i * gbufsize;
-               break;
-       }
+       meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+       kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+       mutex_unlock(&meye.lock);
 
-       case MEYEIOC_G_PARAMS: {
-               struct meye_params *p = arg;
-               *p = meye.params;
-               break;
-       }
+       return 0;
+}
 
-       case MEYEIOC_S_PARAMS: {
-               struct meye_params *jp = arg;
-               if (jp->subsample > 1)
-                       return -EINVAL;
-               if (jp->quality > 10)
-                       return -EINVAL;
-               if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
-                       return -EINVAL;
-               if (jp->framerate > 31)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               if (meye.params.subsample != jp->subsample ||
-                   meye.params.quality != jp->quality)
-                       mchip_hic_stop();       /* need restart */
-               meye.params = *jp;
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
-                                     meye.params.sharpness);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
-                                     meye.params.agc);
-               sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
-                                     meye.params.picture);
-               mutex_unlock(&meye.lock);
-               break;
-       }
+static int meyeioc_sync(struct file *file, void *fh, int *i)
+{
+       int unused;
 
-       case MEYEIOC_QBUF_CAPT: {
-               int *nb = arg;
-
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (*nb >= gbuffers)
-                       return -EINVAL;
-               if (*nb < 0) {
-                       /* stop capture */
-                       mchip_hic_stop();
-                       return 0;
-               }
-               if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
-                       mchip_cont_compression_start();
-               meye.grab_buffer[*nb].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+       if (*i < 0 || *i >= gbuffers)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+       switch (meye.grab_buffer[*i].state) {
+
+       case MEYE_BUF_UNUSED:
                mutex_unlock(&meye.lock);
-               break;
+               return -EINVAL;
+       case MEYE_BUF_USING:
+               if (file->f_flags & O_NONBLOCK) {
+                       mutex_unlock(&meye.lock);
+                       return -EAGAIN;
+               }
+               if (wait_event_interruptible(meye.proc_list,
+                       (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+                       mutex_unlock(&meye.lock);
+                       return -EINTR;
+               }
+               /* fall through */
+       case MEYE_BUF_DONE:
+               meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+               kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
        }
+       *i = meye.grab_buffer[*i].size;
+       mutex_unlock(&meye.lock);
+       return 0;
+}
 
-       case MEYEIOC_SYNC: {
-               int *i = arg;
-               int unused;
+static int meyeioc_stillcapt(void)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
 
-               if (*i < 0 || *i >= gbuffers)
-                       return -EINVAL;
+       if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
 
-               mutex_lock(&meye.lock);
-               switch (meye.grab_buffer[*i].state) {
+       mutex_lock(&meye.lock);
+       meye.grab_buffer[0].state = MEYE_BUF_USING;
+       mchip_take_picture();
 
-               case MEYE_BUF_UNUSED:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               case MEYE_BUF_USING:
-                       if (file->f_flags & O_NONBLOCK) {
-                               mutex_unlock(&meye.lock);
-                               return -EAGAIN;
-                       }
-                       if (wait_event_interruptible(meye.proc_list,
-                                                    (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
-                               mutex_unlock(&meye.lock);
-                               return -EINTR;
-                       }
-                       /* fall through */
-               case MEYE_BUF_DONE:
-                       meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
-                       kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
-               }
-               *i = meye.grab_buffer[*i].size;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       mchip_get_picture(meye.grab_fbuffer,
+                       mchip_hsize() * mchip_vsize() * 2);
 
-       case MEYEIOC_STILLCAPT: {
+       meye.grab_buffer[0].state = MEYE_BUF_DONE;
+       mutex_unlock(&meye.lock);
 
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               meye.grab_buffer[0].state = MEYE_BUF_USING;
+       return 0;
+}
+
+static int meyeioc_stilljcapt(int *len)
+{
+       if (!meye.grab_fbuffer)
+               return -EINVAL;
+
+       if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+               return -EBUSY;
+
+       mutex_lock(&meye.lock);
+       meye.grab_buffer[0].state = MEYE_BUF_USING;
+       *len = -1;
+
+       while (*len == -1) {
                mchip_take_picture();
-               mchip_get_picture(
-                       meye.grab_fbuffer,
-                       mchip_hsize() * mchip_vsize() * 2);
-               meye.grab_buffer[0].state = MEYE_BUF_DONE;
-               mutex_unlock(&meye.lock);
-               break;
+               *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
        }
 
-       case MEYEIOC_STILLJCAPT: {
-               int *len = arg;
-
-               if (!meye.grab_fbuffer)
-                       return -EINVAL;
-               if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
-                       return -EBUSY;
-               mutex_lock(&meye.lock);
-               meye.grab_buffer[0].state = MEYE_BUF_USING;
-               *len = -1;
-               while (*len == -1) {
-                       mchip_take_picture();
-                       *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
-               }
-               meye.grab_buffer[0].state = MEYE_BUF_DONE;
-               mutex_unlock(&meye.lock);
-               break;
-       }
+       meye.grab_buffer[0].state = MEYE_BUF_DONE;
+       mutex_unlock(&meye.lock);
+       return 0;
+}
 
-       case VIDIOC_QUERYCAP: {
-               struct v4l2_capability *cap = arg;
+static int vidioc_querycap(struct file *file, void *fh,
+                               struct v4l2_capability *cap)
+{
+       memset(cap, 0, sizeof(*cap));
+       strcpy(cap->driver, "meye");
+       strcpy(cap->card, "meye");
+       sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
 
-               if (forcev4l1)
-                       return -EINVAL;
+       cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+                      MEYE_DRIVER_MINORVERSION;
 
-               memset(cap, 0, sizeof(*cap));
-               strcpy(cap->driver, "meye");
-               strcpy(cap->card, "meye");
-               sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
-               cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
-                              MEYE_DRIVER_MINORVERSION;
-               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-                                   V4L2_CAP_STREAMING;
-               break;
-       }
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
 
-       case VIDIOC_ENUMINPUT: {
-               struct v4l2_input *i = arg;
+       memset(i, 0, sizeof(*i));
+       i->index = 0;
+       strcpy(i->name, "Camera");
+       i->type = V4L2_INPUT_TYPE_CAMERA;
 
-               if (i->index != 0)
-                       return -EINVAL;
-               memset(i, 0, sizeof(*i));
-               i->index = 0;
-               strcpy(i->name, "Camera");
-               i->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+                               struct v4l2_queryctrl *c)
+{
+       switch (c->id) {
+
+       case V4L2_CID_BRIGHTNESS:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Brightness");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_HUE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Hue");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Contrast");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_SATURATION:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Saturation");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+               c->flags = 0;
+               break;
+       case V4L2_CID_AGC:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Agc");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 48;
+               c->flags = 0;
                break;
+       case V4L2_CID_MEYE_SHARPNESS:
+       case V4L2_CID_SHARPNESS:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Sharpness");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 32;
+
+               /* Continue to report legacy private SHARPNESS ctrl but
+                * say it is disabled in preference to ctrl in the spec
+                */
+               c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
+                                               V4L2_CTRL_FLAG_DISABLED;
+               break;
+       case V4L2_CID_PICTURE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Picture");
+               c->minimum = 0;
+               c->maximum = 63;
+               c->step = 1;
+               c->default_value = 0;
+               c->flags = 0;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "JPEG quality");
+               c->minimum = 0;
+               c->maximum = 10;
+               c->step = 1;
+               c->default_value = 8;
+               c->flags = 0;
+               break;
+       case V4L2_CID_FRAMERATE:
+               c->type = V4L2_CTRL_TYPE_INTEGER;
+               strcpy(c->name, "Framerate");
+               c->minimum = 0;
+               c->maximum = 31;
+               c->step = 1;
+               c->default_value = 0;
+               c->flags = 0;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       case VIDIOC_G_INPUT: {
-               int *i = arg;
+       return 0;
+}
 
-               *i = 0;
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       mutex_lock(&meye.lock);
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+               meye.picture.brightness = c->value << 10;
+               break;
+       case V4L2_CID_HUE:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+               meye.picture.hue = c->value << 10;
+               break;
+       case V4L2_CID_CONTRAST:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+               meye.picture.contrast = c->value << 10;
+               break;
+       case V4L2_CID_SATURATION:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+               meye.picture.colour = c->value << 10;
+               break;
+       case V4L2_CID_AGC:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+               meye.params.agc = c->value;
+               break;
+       case V4L2_CID_SHARPNESS:
+       case V4L2_CID_MEYE_SHARPNESS:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+               meye.params.sharpness = c->value;
+               break;
+       case V4L2_CID_PICTURE:
+               sony_pic_camera_command(
+                       SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+               meye.params.picture = c->value;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               meye.params.quality = c->value;
+               break;
+       case V4L2_CID_FRAMERATE:
+               meye.params.framerate = c->value;
                break;
+       default:
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
+       mutex_unlock(&meye.lock);
 
-       case VIDIOC_S_INPUT: {
-               int *i = arg;
+       return 0;
+}
 
-               if (*i != 0)
-                       return -EINVAL;
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+       mutex_lock(&meye.lock);
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = meye.picture.brightness >> 10;
+               break;
+       case V4L2_CID_HUE:
+               c->value = meye.picture.hue >> 10;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->value = meye.picture.contrast >> 10;
+               break;
+       case V4L2_CID_SATURATION:
+               c->value = meye.picture.colour >> 10;
+               break;
+       case V4L2_CID_AGC:
+               c->value = meye.params.agc;
+               break;
+       case V4L2_CID_SHARPNESS:
+       case V4L2_CID_MEYE_SHARPNESS:
+               c->value = meye.params.sharpness;
                break;
+       case V4L2_CID_PICTURE:
+               c->value = meye.params.picture;
+               break;
+       case V4L2_CID_JPEGQUAL:
+               c->value = meye.params.quality;
+               break;
+       case V4L2_CID_FRAMERATE:
+               c->value = meye.params.framerate;
+               break;
+       default:
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
+       mutex_unlock(&meye.lock);
 
-       case VIDIOC_QUERYCTRL: {
-               struct v4l2_queryctrl *c = arg;
+       return 0;
+}
 
-               switch (c->id) {
+static int vidioc_enum_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_fmtdesc *f)
+{
+       if (f->index > 1)
+               return -EINVAL;
 
-               case V4L2_CID_BRIGHTNESS:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Brightness");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_HUE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Hue");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Contrast");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_SATURATION:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Saturation");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_AGC:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Agc");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 48;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Sharpness");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 32;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_PICTURE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Picture");
-                       c->minimum = 0;
-                       c->maximum = 63;
-                       c->step = 1;
-                       c->default_value = 0;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "JPEG quality");
-                       c->minimum = 0;
-                       c->maximum = 10;
-                       c->step = 1;
-                       c->default_value = 8;
-                       c->flags = 0;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       c->type = V4L2_CTRL_TYPE_INTEGER;
-                       strcpy(c->name, "Framerate");
-                       c->minimum = 0;
-                       c->maximum = 31;
-                       c->step = 1;
-                       c->default_value = 0;
-                       c->flags = 0;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->index == 0) {
+               /* standard YUV 422 capture */
+               memset(f, 0, sizeof(*f));
+               f->index = 0;
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->flags = 0;
+               strcpy(f->description, "YUV422");
+               f->pixelformat = V4L2_PIX_FMT_YUYV;
+       } else {
+               /* compressed MJPEG capture */
+               memset(f, 0, sizeof(*f));
+               f->index = 1;
+               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               f->flags = V4L2_FMT_FLAG_COMPRESSED;
+               strcpy(f->description, "MJPEG");
+               f->pixelformat = V4L2_PIX_FMT_MJPEG;
        }
 
-       case VIDIOC_S_CTRL: {
-               struct v4l2_control *c = arg;
+       return 0;
+}
 
-               mutex_lock(&meye.lock);
-               switch (c->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
-                       meye.picture.brightness = c->value << 10;
-                       break;
-               case V4L2_CID_HUE:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
-                       meye.picture.hue = c->value << 10;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
-                       meye.picture.contrast = c->value << 10;
-                       break;
-               case V4L2_CID_SATURATION:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
-                       meye.picture.colour = c->value << 10;
-                       break;
-               case V4L2_CID_AGC:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
-                       meye.params.agc = c->value;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
-                       meye.params.sharpness = c->value;
-                       break;
-               case V4L2_CID_PICTURE:
-                       sony_pic_camera_command(
-                               SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
-                       meye.params.picture = c->value;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       meye.params.quality = c->value;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       meye.params.framerate = c->value;
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               mutex_unlock(&meye.lock);
-               break;
+static int vidioc_try_fmt_cap(struct file *file, void *fh,
+                               struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+           f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+           f->fmt.pix.field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+
+       if (f->fmt.pix.width <= 320) {
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+       } else {
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
        }
 
-       case VIDIOC_G_CTRL: {
-               struct v4l2_control *c = arg;
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
 
-               mutex_lock(&meye.lock);
-               switch (c->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       c->value = meye.picture.brightness >> 10;
-                       break;
-               case V4L2_CID_HUE:
-                       c->value = meye.picture.hue >> 10;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       c->value = meye.picture.contrast >> 10;
-                       break;
-               case V4L2_CID_SATURATION:
-                       c->value = meye.picture.colour >> 10;
-                       break;
-               case V4L2_CID_AGC:
-                       c->value = meye.params.agc;
-                       break;
-               case V4L2_CID_SHARPNESS:
-                       c->value = meye.params.sharpness;
-                       break;
-               case V4L2_CID_PICTURE:
-                       c->value = meye.params.picture;
-                       break;
-               case V4L2_CID_JPEGQUAL:
-                       c->value = meye.params.quality;
-                       break;
-               case V4L2_CID_FRAMERATE:
-                       c->value = meye.params.framerate;
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               mutex_unlock(&meye.lock);
+       return 0;
+}
+
+static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       switch (meye.mchip_mode) {
+       case MCHIP_HIC_MODE_CONT_OUT:
+       default:
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+               break;
+       case MCHIP_HIC_MODE_CONT_COMP:
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
                break;
        }
 
-       case VIDIOC_ENUM_FMT: {
-               struct v4l2_fmtdesc *f = arg;
-
-               if (f->index > 1)
-                       return -EINVAL;
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->index == 0) {
-                       /* standard YUV 422 capture */
-                       memset(f, 0, sizeof(*f));
-                       f->index = 0;
-                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       f->flags = 0;
-                       strcpy(f->description, "YUV422");
-                       f->pixelformat = V4L2_PIX_FMT_YUYV;
-               } else {
-                       /* compressed MJPEG capture */
-                       memset(f, 0, sizeof(*f));
-                       f->index = 1;
-                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-                       strcpy(f->description, "MJPEG");
-                       f->pixelformat = V4L2_PIX_FMT_MJPEG;
-               }
-               break;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.width = mchip_hsize();
+       f->fmt.pix.height = mchip_vsize();
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+           f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+           f->fmt.pix.field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       mutex_lock(&meye.lock);
+
+       if (f->fmt.pix.width <= 320) {
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+               meye.params.subsample = 1;
+       } else {
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
+               meye.params.subsample = 0;
        }
 
-       case VIDIOC_TRY_FMT: {
-               struct v4l2_format *f = arg;
-
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
-                   f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-                       return -EINVAL;
-               if (f->fmt.pix.field != V4L2_FIELD_ANY &&
-                   f->fmt.pix.field != V4L2_FIELD_NONE)
-                       return -EINVAL;
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               if (f->fmt.pix.width <= 320) {
-                       f->fmt.pix.width = 320;
-                       f->fmt.pix.height = 240;
-               } else {
-                       f->fmt.pix.width = 640;
-                       f->fmt.pix.height = 480;
-               }
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
+       switch (f->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+               meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+               break;
+       case V4L2_PIX_FMT_MJPEG:
+               meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
                break;
        }
 
-       case VIDIOC_G_FMT: {
-               struct v4l2_format *f = arg;
+       mutex_unlock(&meye.lock);
+       f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       f->fmt.pix.sizeimage = f->fmt.pix.height *
+                              f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = 0;
+       f->fmt.pix.priv = 0;
 
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               switch (meye.mchip_mode) {
-               case MCHIP_HIC_MODE_CONT_OUT:
-               default:
-                       f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-                       break;
-               case MCHIP_HIC_MODE_CONT_COMP:
-                       f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
-                       break;
-               }
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               f->fmt.pix.width = mchip_hsize();
-               f->fmt.pix.height = mchip_vsize();
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
-               break;
-       }
+       return 0;
+}
 
-       case VIDIOC_S_FMT: {
-               struct v4l2_format *f = arg;
-
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
-                   f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-                       return -EINVAL;
-               if (f->fmt.pix.field != V4L2_FIELD_ANY &&
-                   f->fmt.pix.field != V4L2_FIELD_NONE)
-                       return -EINVAL;
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-               mutex_lock(&meye.lock);
-               if (f->fmt.pix.width <= 320) {
-                       f->fmt.pix.width = 320;
-                       f->fmt.pix.height = 240;
-                       meye.params.subsample = 1;
-               } else {
-                       f->fmt.pix.width = 640;
-                       f->fmt.pix.height = 480;
-                       meye.params.subsample = 0;
-               }
-               switch (f->fmt.pix.pixelformat) {
-               case V4L2_PIX_FMT_YUYV:
-                       meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
-                       break;
-               case V4L2_PIX_FMT_MJPEG:
-                       meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
-                       break;
-               }
-               mutex_unlock(&meye.lock);
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-               f->fmt.pix.sizeimage = f->fmt.pix.height *
-                                      f->fmt.pix.bytesperline;
-               f->fmt.pix.colorspace = 0;
-               f->fmt.pix.priv = 0;
+static int vidioc_reqbufs(struct file *file, void *fh,
+                               struct v4l2_requestbuffers *req)
+{
+       int i;
 
-               break;
-       }
+       if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
 
-       case VIDIOC_REQBUFS: {
-               struct v4l2_requestbuffers *req = arg;
-               int i;
+       if (req->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
 
-               if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (req->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
-               if (meye.grab_fbuffer && req->count == gbuffers) {
-                       /* already allocated, no modifications */
-                       break;
-               }
-               mutex_lock(&meye.lock);
-               if (meye.grab_fbuffer) {
-                       for (i = 0; i < gbuffers; i++)
-                               if (meye.vma_use_count[i]) {
-                                       mutex_unlock(&meye.lock);
-                                       return -EINVAL;
-                               }
-                       rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
-                       meye.grab_fbuffer = NULL;
-               }
-               gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
-               req->count = gbuffers;
-               meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
-               if (!meye.grab_fbuffer) {
-                       printk(KERN_ERR "meye: v4l framebuffer allocation"
-                                       " failed\n");
-                       mutex_unlock(&meye.lock);
-                       return -ENOMEM;
-               }
-               for (i = 0; i < gbuffers; i++)
-                       meye.vma_use_count[i] = 0;
-               mutex_unlock(&meye.lock);
-               break;
+       if (meye.grab_fbuffer && req->count == gbuffers) {
+               /* already allocated, no modifications */
+               return 0;
        }
 
-       case VIDIOC_QUERYBUF: {
-               struct v4l2_buffer *buf = arg;
-               int index = buf->index;
-
-               if (index < 0 || index >= gbuffers)
-                       return -EINVAL;
-               memset(buf, 0, sizeof(*buf));
-               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               buf->index = index;
-               buf->bytesused = meye.grab_buffer[index].size;
-               buf->flags = V4L2_BUF_FLAG_MAPPED;
-               if (meye.grab_buffer[index].state == MEYE_BUF_USING)
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-               buf->field = V4L2_FIELD_NONE;
-               buf->timestamp = meye.grab_buffer[index].timestamp;
-               buf->sequence = meye.grab_buffer[index].sequence;
-               buf->memory = V4L2_MEMORY_MMAP;
-               buf->m.offset = index * gbufsize;
-               buf->length = gbufsize;
-               break;
+       mutex_lock(&meye.lock);
+       if (meye.grab_fbuffer) {
+               for (i = 0; i < gbuffers; i++)
+                       if (meye.vma_use_count[i]) {
+                               mutex_unlock(&meye.lock);
+                               return -EINVAL;
+                       }
+               rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+               meye.grab_fbuffer = NULL;
        }
 
-       case VIDIOC_QBUF: {
-               struct v4l2_buffer *buf = arg;
-
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (buf->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
-               if (buf->index < 0 || buf->index >= gbuffers)
-                       return -EINVAL;
-               if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
-                       return -EINVAL;
-               mutex_lock(&meye.lock);
-               buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               buf->flags &= ~V4L2_BUF_FLAG_DONE;
-               meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
-               kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+       gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+       req->count = gbuffers;
+       meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+
+       if (!meye.grab_fbuffer) {
+               printk(KERN_ERR "meye: v4l framebuffer allocation"
+                               " failed\n");
                mutex_unlock(&meye.lock);
-               break;
+               return -ENOMEM;
        }
 
-       case VIDIOC_DQBUF: {
-               struct v4l2_buffer *buf = arg;
-               int reqnr;
+       for (i = 0; i < gbuffers; i++)
+               meye.vma_use_count[i] = 0;
 
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (buf->memory != V4L2_MEMORY_MMAP)
-                       return -EINVAL;
+       mutex_unlock(&meye.lock);
 
-               mutex_lock(&meye.lock);
-               if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&meye.lock);
-                       return -EAGAIN;
-               }
-               if (wait_event_interruptible(meye.proc_list,
-                                            kfifo_len(meye.doneq) != 0) < 0) {
-                       mutex_unlock(&meye.lock);
-                       return -EINTR;
-               }
-               if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
-                              sizeof(int))) {
-                       mutex_unlock(&meye.lock);
-                       return -EBUSY;
-               }
-               if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
-               buf->index = reqnr;
-               buf->bytesused = meye.grab_buffer[reqnr].size;
-               buf->flags = V4L2_BUF_FLAG_MAPPED;
-               buf->field = V4L2_FIELD_NONE;
-               buf->timestamp = meye.grab_buffer[reqnr].timestamp;
-               buf->sequence = meye.grab_buffer[reqnr].sequence;
-               buf->memory = V4L2_MEMORY_MMAP;
-               buf->m.offset = reqnr * gbufsize;
-               buf->length = gbufsize;
-               meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+       return 0;
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       int index = buf->index;
+
+       if (index < 0 || index >= gbuffers)
+               return -EINVAL;
+
+       memset(buf, 0, sizeof(*buf));
+
+       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf->index = index;
+       buf->bytesused = meye.grab_buffer[index].size;
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+       if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+               buf->flags |= V4L2_BUF_FLAG_QUEUED;
+
+       if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+               buf->flags |= V4L2_BUF_FLAG_DONE;
+
+       buf->field = V4L2_FIELD_NONE;
+       buf->timestamp = meye.grab_buffer[index].timestamp;
+       buf->sequence = meye.grab_buffer[index].sequence;
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->m.offset = index * gbufsize;
+       buf->length = gbufsize;
+
+       return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       if (buf->index < 0 || buf->index >= gbuffers)
+               return -EINVAL;
+
+       if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+       kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+       mutex_unlock(&meye.lock);
+
+       return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       int reqnr;
+
+       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       mutex_lock(&meye.lock);
+
+       if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EAGAIN;
        }
 
-       case VIDIOC_STREAMON: {
-               mutex_lock(&meye.lock);
-               switch (meye.mchip_mode) {
-               case MCHIP_HIC_MODE_CONT_OUT:
-                       mchip_continuous_start();
-                       break;
-               case MCHIP_HIC_MODE_CONT_COMP:
-                       mchip_cont_compression_start();
-                       break;
-               default:
-                       mutex_unlock(&meye.lock);
-                       return -EINVAL;
-               }
+       if (wait_event_interruptible(meye.proc_list,
+                                    kfifo_len(meye.doneq) != 0) < 0) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EINTR;
        }
 
-       case VIDIOC_STREAMOFF: {
-               int i;
+       if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
+                      sizeof(int))) {
+               mutex_unlock(&meye.lock);
+               return -EBUSY;
+       }
 
-               mutex_lock(&meye.lock);
-               mchip_hic_stop();
-               kfifo_reset(meye.grabq);
-               kfifo_reset(meye.doneq);
-               for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
-                       meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+       if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
                mutex_unlock(&meye.lock);
-               break;
+               return -EINVAL;
        }
 
-       /*
-        * XXX what about private snapshot ioctls ?
-        * Do they need to be converted to V4L2 ?
-       */
+       buf->index = reqnr;
+       buf->bytesused = meye.grab_buffer[reqnr].size;
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+       buf->field = V4L2_FIELD_NONE;
+       buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+       buf->sequence = meye.grab_buffer[reqnr].sequence;
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->m.offset = reqnr * gbufsize;
+       buf->length = gbufsize;
+       meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+       mutex_unlock(&meye.lock);
+
+       return 0;
+}
 
+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+       mutex_lock(&meye.lock);
+
+       switch (meye.mchip_mode) {
+       case MCHIP_HIC_MODE_CONT_OUT:
+               mchip_continuous_start();
+               break;
+       case MCHIP_HIC_MODE_CONT_COMP:
+               mchip_cont_compression_start();
+               break;
        default:
-               return -ENOIOCTLCMD;
+               mutex_unlock(&meye.lock);
+               return -EINVAL;
        }
 
+       mutex_unlock(&meye.lock);
+
        return 0;
 }
 
-static int meye_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 {
-       return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
+       mutex_lock(&meye.lock);
+       mchip_hic_stop();
+       kfifo_reset(meye.grabq);
+       kfifo_reset(meye.doneq);
+
+       for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+               meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+
+       mutex_unlock(&meye.lock);
+       return 0;
+}
+
+static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+       switch (cmd) {
+       case MEYEIOC_G_PARAMS:
+               return meyeioc_g_params((struct meye_params *) arg);
+
+       case MEYEIOC_S_PARAMS:
+               return meyeioc_s_params((struct meye_params *) arg);
+
+       case MEYEIOC_QBUF_CAPT:
+               return meyeioc_qbuf_capt((int *) arg);
+
+       case MEYEIOC_SYNC:
+               return meyeioc_sync(file, fh, (int *) arg);
+
+       case MEYEIOC_STILLCAPT:
+               return meyeioc_stillcapt();
+
+       case MEYEIOC_STILLJCAPT:
+               return meyeioc_stilljcapt((int *) arg);
+
+       default:
+               return -EINVAL;
+       }
+
 }
 
 static unsigned int meye_poll(struct file *file, poll_table *wait)
@@ -1752,8 +1687,10 @@ static const struct file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = meye_ioctl,
+       .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .poll           = meye_poll,
        .llseek         = no_llseek,
 };
@@ -1765,6 +1702,24 @@ static struct video_device meye_template = {
        .fops           = &meye_fops,
        .release        = video_device_release,
        .minor          = -1,
+       .vidioc_querycap        = vidioc_querycap,
+       .vidioc_enum_input      = vidioc_enum_input,
+       .vidioc_g_input         = vidioc_g_input,
+       .vidioc_s_input         = vidioc_s_input,
+       .vidioc_queryctrl       = vidioc_queryctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_enum_fmt_cap    = vidioc_enum_fmt_cap,
+       .vidioc_try_fmt_cap     = vidioc_try_fmt_cap,
+       .vidioc_g_fmt_cap       = vidioc_g_fmt_cap,
+       .vidioc_s_fmt_cap       = vidioc_s_fmt_cap,
+       .vidioc_reqbufs         = vidioc_reqbufs,
+       .vidioc_querybuf        = vidioc_querybuf,
+       .vidioc_qbuf            = vidioc_qbuf,
+       .vidioc_dqbuf           = vidioc_dqbuf,
+       .vidioc_streamon        = vidioc_streamon,
+       .vidioc_streamoff       = vidioc_streamoff,
+       .vidioc_default         = vidioc_default,
 };
 
 #ifdef CONFIG_PM
index 7a11f3159e32b755a3a435b6872590b35f0dc845..b73c740f7fb2697a5e128feee6de2f49abeec192 100644 (file)
@@ -366,7 +366,7 @@ int msp_sleep(struct msp_state *state, int timeout)
 }
 
 /* ------------------------------------------------------------------------ */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
 static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
 {
        if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -514,7 +514,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
           kernel pointer here... */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
        case VIDIOCGAUDIO:
        {
                struct video_audio *va = arg;
index 61ec794a737e2f438072a06e9e0272bb274e2a3f..7f5568592793c836f8a71d78181f83c6dcf2c648 100644 (file)
@@ -833,11 +833,6 @@ static int msp34xxg_modus(struct i2c_client *client)
                v4l_dbg(1, msp_debug, client, "selected radio modus\n");
                return 0x0001;
        }
-
-       if (state->v4l2_std & V4L2_STD_PAL) {
-               v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
-               return 0x7001;
-       }
        if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
                v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
                return 0x4001;
@@ -846,15 +841,15 @@ static int msp34xxg_modus(struct i2c_client *client)
                v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
                return 0x0001;
        }
+       if (state->v4l2_std == V4L2_STD_SECAM_L) {
+               v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
+               return 0x6001;
+       }
        if (state->v4l2_std & V4L2_STD_MN) {
                v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
                return 0x2001;
        }
-       if (state->v4l2_std & V4L2_STD_SECAM) {
-               v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
-               return 0x6001;
-       }
-       return 0x0001;
+       return 0x7001;
 }
 
 static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
index 74fd6a01d4c4060b05037f93d7069715b0b41433..fbcb28233737c86182b89b73c133a428083547cd 100644 (file)
 #include "tuner-i2c.h"
 #include "mt20xx.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "mt20xx"
-
 /* ---------------------------------------------------------------------- */
 
 static unsigned int optimize_vco  = 1;
@@ -24,7 +22,7 @@ module_param(optimize_vco,      int, 0644);
 static unsigned int tv_antenna    = 1;
 module_param(tv_antenna,        int, 0644);
 
-static unsigned int radio_antenna = 0;
+static unsigned int radio_antenna;
 module_param(radio_antenna,     int, 0644);
 
 /* ---------------------------------------------------------------------- */
@@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr = i2c_addr;
        priv->i2c_props.adap = i2c_adap;
+       priv->i2c_props.name = "mt20xx";
 
        //priv->radio_if2 = 10700 * 1000;       /* 10.7MHz - FM radio */
 
index 5e9c825d2e91bb392d283d04a776c6aa7dc1de11..aa848e14ce5e75bbf43b8edecc057fdc209af33b 100644 (file)
@@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
                                             struct i2c_adapter* i2c_adap,
                                             u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
new file mode 100644 (file)
index 0000000..3fb5f63
--- /dev/null
@@ -0,0 +1,722 @@
+/*
+ * Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+#include <asm/gpio.h>
+#endif
+
+/* mt9m001 i2c address 0x5d
+ * The platform has to define i2c_board_info
+ * and call i2c_register_board_info() */
+
+/* mt9m001 selected register addresses */
+#define MT9M001_CHIP_VERSION           0x00
+#define MT9M001_ROW_START              0x01
+#define MT9M001_COLUMN_START           0x02
+#define MT9M001_WINDOW_HEIGHT          0x03
+#define MT9M001_WINDOW_WIDTH           0x04
+#define MT9M001_HORIZONTAL_BLANKING    0x05
+#define MT9M001_VERTICAL_BLANKING      0x06
+#define MT9M001_OUTPUT_CONTROL         0x07
+#define MT9M001_SHUTTER_WIDTH          0x09
+#define MT9M001_FRAME_RESTART          0x0b
+#define MT9M001_SHUTTER_DELAY          0x0c
+#define MT9M001_RESET                  0x0d
+#define MT9M001_READ_OPTIONS1          0x1e
+#define MT9M001_READ_OPTIONS2          0x20
+#define MT9M001_GLOBAL_GAIN            0x35
+#define MT9M001_CHIP_ENABLE            0xF1
+
+static const struct soc_camera_data_format mt9m001_colour_formats[] = {
+       /* Order important: first natively supported,
+        * second supported with a GPIO extender */
+       {
+               .name           = "Bayer (sRGB) 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_SBGGR16,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }, {
+               .name           = "Bayer (sRGB) 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }
+};
+
+static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
+       /* Order important - see above */
+       {
+               .name           = "Monochrome 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_Y16,
+       }, {
+               .name           = "Monochrome 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_GREY,
+       },
+};
+
+struct mt9m001 {
+       struct i2c_client *client;
+       struct soc_camera_device icd;
+       int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+       int switch_gpio;
+       unsigned char autoexposure;
+       unsigned char datawidth;
+};
+
+static int reg_read(struct soc_camera_device *icd, const u8 reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       struct i2c_client *client = mt9m001->client;
+       s32 data = i2c_smbus_read_word_data(client, reg);
+       return data < 0 ? data : swab16(data);
+}
+
+static int reg_write(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
+}
+
+static int reg_set(struct soc_camera_device *icd, const u8 reg,
+                  const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret | data);
+}
+
+static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9m001_init(struct soc_camera_device *icd)
+{
+       int ret;
+
+       /* Disable chip, synchronous option update */
+       dev_dbg(icd->vdev->dev, "%s\n", __func__);
+
+       ret = reg_write(icd, MT9M001_RESET, 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_RESET, 0);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+
+       return ret >= 0 ? 0 : -EIO;
+}
+
+static int mt9m001_release(struct soc_camera_device *icd)
+{
+       /* Disable the chip */
+       reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+       return 0;
+}
+
+static int mt9m001_start_capture(struct soc_camera_device *icd)
+{
+       /* Switch to master "normal" mode */
+       if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int mt9m001_stop_capture(struct soc_camera_device *icd)
+{
+       /* Stop sensor readout */
+       if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int bus_switch_request(struct mt9m001 *mt9m001,
+                             struct soc_camera_link *icl)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       int ret;
+       unsigned int gpio = icl->gpio;
+
+       if (gpio_is_valid(gpio)) {
+               /* We have a data bus switch. */
+               ret = gpio_request(gpio, "mt9m001");
+               if (ret < 0) {
+                       dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
+                               gpio);
+                       return ret;
+               }
+
+               ret = gpio_direction_output(gpio, 0);
+               if (ret < 0) {
+                       dev_err(&mt9m001->client->dev,
+                               "Cannot set GPIO %u to output\n", gpio);
+                       gpio_free(gpio);
+                       return ret;
+               }
+       }
+
+       mt9m001->switch_gpio = gpio;
+#else
+       mt9m001->switch_gpio = -EINVAL;
+#endif
+       return 0;
+}
+
+static void bus_switch_release(struct mt9m001 *mt9m001)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       if (gpio_is_valid(mt9m001->switch_gpio))
+               gpio_free(mt9m001->switch_gpio);
+#endif
+}
+
+static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       if (!gpio_is_valid(mt9m001->switch_gpio))
+               return -ENODEV;
+
+       gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static int bus_switch_possible(struct mt9m001 *mt9m001)
+{
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+       return gpio_is_valid(mt9m001->switch_gpio);
+#else
+       return 0;
+#endif
+}
+
+static int mt9m001_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
+       int ret;
+
+       /* Flags validity verified in test_bus_param */
+
+       if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
+           (mt9m001->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
+           (mt9m001->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
+               /* Well, we actually only can do 10 or 8 bits... */
+               if (width_flag == SOCAM_DATAWIDTH_9)
+                       return -EINVAL;
+               ret = bus_switch_act(mt9m001,
+                                    width_flag == SOCAM_DATAWIDTH_8);
+               if (ret < 0)
+                       return ret;
+
+               mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
+       }
+
+       return 0;
+}
+
+static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       unsigned int width_flag = SOCAM_DATAWIDTH_10;
+
+       if (bus_switch_possible(mt9m001))
+               width_flag |= SOCAM_DATAWIDTH_8;
+
+       /* MT9M001 has all capture_format parameters fixed */
+       return SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_HSYNC_ACTIVE_HIGH |
+               SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_MASTER |
+               width_flag;
+}
+
+static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
+               __u32 pixfmt, struct v4l2_rect *rect)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       int ret;
+       const u16 hblank = 9, vblank = 25;
+
+       /* Blanking and start values - default... */
+       ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
+
+       /* The caller provides a supported format, as verified per
+        * call to icd->try_fmt_cap() */
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_ROW_START, rect->top);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
+                               rect->height + icd->y_skip_top - 1);
+       if (ret >= 0 && mt9m001->autoexposure) {
+               ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
+                               rect->height + icd->y_skip_top + vblank);
+               if (ret >= 0) {
+                       const struct v4l2_queryctrl *qctrl =
+                               soc_camera_find_qctrl(icd->ops,
+                                                     V4L2_CID_EXPOSURE);
+                       icd->exposure = (524 + (rect->height + icd->y_skip_top +
+                                               vblank - 1) *
+                                        (qctrl->maximum - qctrl->minimum)) /
+                               1048 + qctrl->minimum;
+               }
+       }
+
+       return ret < 0 ? ret : 0;
+}
+
+static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
+                              struct v4l2_format *f)
+{
+       if (f->fmt.pix.height < 32 + icd->y_skip_top)
+               f->fmt.pix.height = 32 + icd->y_skip_top;
+       if (f->fmt.pix.height > 1024 + icd->y_skip_top)
+               f->fmt.pix.height = 1024 + icd->y_skip_top;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 1280)
+               f->fmt.pix.width = 1280;
+       f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */
+
+       return 0;
+}
+
+static int mt9m001_get_chip_id(struct soc_camera_device *icd,
+                              struct v4l2_chip_ident *id)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       id->ident       = mt9m001->model;
+       id->revision    = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m001_get_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       reg->val = reg_read(icd, reg->reg);
+
+       if (reg->val > 0xffff)
+               return -EIO;
+
+       return 0;
+}
+
+static int mt9m001_set_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9m001->client->addr)
+               return -ENODEV;
+
+       if (reg_write(icd, reg->reg, reg->val) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+const struct v4l2_queryctrl mt9m001_controls[] = {
+       {
+               .id             = V4L2_CID_VFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Vertically",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_GAIN,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Gain",
+               .minimum        = 0,
+               .maximum        = 127,
+               .step           = 1,
+               .default_value  = 64,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Exposure",
+               .minimum        = 1,
+               .maximum        = 255,
+               .step           = 1,
+               .default_value  = 255,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Exposure",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }
+};
+
+static int mt9m001_video_probe(struct soc_camera_device *);
+static void mt9m001_video_remove(struct soc_camera_device *);
+static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
+static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
+
+static struct soc_camera_ops mt9m001_ops = {
+       .owner                  = THIS_MODULE,
+       .probe                  = mt9m001_video_probe,
+       .remove                 = mt9m001_video_remove,
+       .init                   = mt9m001_init,
+       .release                = mt9m001_release,
+       .start_capture          = mt9m001_start_capture,
+       .stop_capture           = mt9m001_stop_capture,
+       .set_fmt_cap            = mt9m001_set_fmt_cap,
+       .try_fmt_cap            = mt9m001_try_fmt_cap,
+       .set_bus_param          = mt9m001_set_bus_param,
+       .query_bus_param        = mt9m001_query_bus_param,
+       .controls               = mt9m001_controls,
+       .num_controls           = ARRAY_SIZE(mt9m001_controls),
+       .get_control            = mt9m001_get_control,
+       .set_control            = mt9m001_set_control,
+       .get_chip_id            = mt9m001_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .get_register           = mt9m001_get_register,
+       .set_register           = mt9m001_set_register,
+#endif
+};
+
+static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       int data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               data = reg_read(icd, MT9M001_READ_OPTIONS2);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x8000);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               ctrl->value = mt9m001->autoexposure;
+               break;
+       }
+       return 0;
+}
+
+static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       const struct v4l2_queryctrl *qctrl;
+       int data;
+
+       qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
+
+       if (!qctrl)
+               return -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
+               else
+                       data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_GAIN:
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               /* See Datasheet Table 7, Gain settings. */
+               if (ctrl->value <= qctrl->default_value) {
+                       /* Pack it into 0..1 step 0.125, register values 0..8 */
+                       unsigned long range = qctrl->default_value - qctrl->minimum;
+                       data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+
+                       dev_dbg(&icd->dev, "Setting gain %d\n", data);
+                       data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+                       if (data < 0)
+                               return -EIO;
+               } else {
+                       /* Pack it into 1.125..15 variable step, register values 9..67 */
+                       /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
+                       unsigned long range = qctrl->maximum - qctrl->default_value - 1;
+                       unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+                                              111 + range / 2) / range + 9;
+
+                       if (gain <= 32)
+                               data = gain;
+                       else if (gain <= 64)
+                               data = ((gain - 32) * 16 + 16) / 32 + 80;
+                       else
+                               data = ((gain - 64) * 7 + 28) / 56 + 96;
+
+                       dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
+                                reg_read(icd, MT9M001_GLOBAL_GAIN), data);
+                       data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+                       if (data < 0)
+                               return -EIO;
+               }
+
+               /* Success */
+               icd->gain = ctrl->value;
+               break;
+       case V4L2_CID_EXPOSURE:
+               /* mt9m001 has maximum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
+                                                range / 2) / range + 1;
+
+                       dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
+                                reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
+                       if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+                               return -EIO;
+                       icd->exposure = ctrl->value;
+                       mt9m001->autoexposure = 0;
+               }
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->value) {
+                       const u16 vblank = 25;
+                       if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
+                                     icd->y_skip_top + vblank) < 0)
+                               return -EIO;
+                       qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+                       icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) *
+                                        (qctrl->maximum - qctrl->minimum)) /
+                               1048 + qctrl->minimum;
+                       mt9m001->autoexposure = 1;
+               } else
+                       mt9m001->autoexposure = 0;
+               break;
+       }
+       return 0;
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int mt9m001_video_probe(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       s32 data;
+       int ret;
+
+       /* We must have a parent by now. And it cannot be a wrong one.
+        * So this entire test is completely redundant. */
+       if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       /* Enable the chip */
+       data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1);
+       dev_dbg(&icd->dev, "write: %d\n", data);
+
+       /* Read out the chip version register */
+       data = reg_read(icd, MT9M001_CHIP_VERSION);
+
+       /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
+       switch (data) {
+       case 0x8411:
+       case 0x8421:
+               mt9m001->model = V4L2_IDENT_MT9M001C12ST;
+               icd->formats = mt9m001_colour_formats;
+               if (mt9m001->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
+               else
+                       icd->num_formats = 1;
+               break;
+       case 0x8431:
+               mt9m001->model = V4L2_IDENT_MT9M001C12STM;
+               icd->formats = mt9m001_monochrome_formats;
+               if (mt9m001->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
+               else
+                       icd->num_formats = 1;
+               break;
+       default:
+               ret = -ENODEV;
+               dev_err(&icd->dev,
+                       "No MT9M001 chip detected, register read %x\n", data);
+               goto ei2c;
+       }
+
+       dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
+                data == 0x8431 ? "C12STM" : "C12ST");
+
+       /* Now that we know the model, we can start video */
+       ret = soc_camera_video_start(icd);
+       if (ret)
+               goto eisis;
+
+       return 0;
+
+eisis:
+ei2c:
+       return ret;
+}
+
+static void mt9m001_video_remove(struct soc_camera_device *icd)
+{
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+
+       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
+               mt9m001->icd.dev.parent, mt9m001->icd.vdev);
+       soc_camera_video_stop(&mt9m001->icd);
+}
+
+static int mt9m001_probe(struct i2c_client *client)
+{
+       struct mt9m001 *mt9m001;
+       struct soc_camera_device *icd;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_link *icl = client->dev.platform_data;
+       int ret;
+
+       if (!icl) {
+               dev_err(&client->dev, "MT9M001 driver needs platform data\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+               return -EIO;
+       }
+
+       mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
+       if (!mt9m001)
+               return -ENOMEM;
+
+       mt9m001->client = client;
+       i2c_set_clientdata(client, mt9m001);
+
+       /* Second stage probe - when a capture adapter is there */
+       icd = &mt9m001->icd;
+       icd->ops        = &mt9m001_ops;
+       icd->control    = &client->dev;
+       icd->x_min      = 20;
+       icd->y_min      = 12;
+       icd->x_current  = 20;
+       icd->y_current  = 12;
+       icd->width_min  = 48;
+       icd->width_max  = 1280;
+       icd->height_min = 32;
+       icd->height_max = 1024;
+       icd->y_skip_top = 1;
+       icd->iface      = icl->bus_id;
+       /* Default datawidth - this is the only width this camera (normally)
+        * supports. It is only with extra logic that it can support
+        * other widths. Therefore it seems to be a sensible default. */
+       mt9m001->datawidth = 10;
+       /* Simulated autoexposure. If enabled, we calculate shutter width
+        * ourselves in the driver based on vertical blanking and frame width */
+       mt9m001->autoexposure = 1;
+
+       ret = bus_switch_request(mt9m001, icl);
+       if (ret)
+               goto eswinit;
+
+       ret = soc_camera_device_register(icd);
+       if (ret)
+               goto eisdr;
+
+       return 0;
+
+eisdr:
+       bus_switch_release(mt9m001);
+eswinit:
+       kfree(mt9m001);
+       return ret;
+}
+
+static int mt9m001_remove(struct i2c_client *client)
+{
+       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+
+       soc_camera_device_unregister(&mt9m001->icd);
+       bus_switch_release(mt9m001);
+       kfree(mt9m001);
+
+       return 0;
+}
+
+static struct i2c_driver mt9m001_i2c_driver = {
+       .driver = {
+               .name = "mt9m001",
+       },
+       .probe          = mt9m001_probe,
+       .remove         = mt9m001_remove,
+};
+
+static int __init mt9m001_mod_init(void)
+{
+       return i2c_add_driver(&mt9m001_i2c_driver);
+}
+
+static void __exit mt9m001_mod_exit(void)
+{
+       i2c_del_driver(&mt9m001_i2c_driver);
+}
+
+module_init(mt9m001_mod_init);
+module_exit(mt9m001_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
new file mode 100644 (file)
index 0000000..d4b9e27
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * Driver for MT9V022 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+#ifdef CONFIG_MT9M001_PCA9536_SWITCH
+#include <asm/gpio.h>
+#endif
+
+/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
+ * The platform has to define i2c_board_info
+ * and call i2c_register_board_info() */
+
+static char *sensor_type;
+module_param(sensor_type, charp, S_IRUGO);
+MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n");
+
+/* mt9v022 selected register addresses */
+#define MT9V022_CHIP_VERSION           0x00
+#define MT9V022_COLUMN_START           0x01
+#define MT9V022_ROW_START              0x02
+#define MT9V022_WINDOW_HEIGHT          0x03
+#define MT9V022_WINDOW_WIDTH           0x04
+#define MT9V022_HORIZONTAL_BLANKING    0x05
+#define MT9V022_VERTICAL_BLANKING      0x06
+#define MT9V022_CHIP_CONTROL           0x07
+#define MT9V022_SHUTTER_WIDTH1         0x08
+#define MT9V022_SHUTTER_WIDTH2         0x09
+#define MT9V022_SHUTTER_WIDTH_CTRL     0x0a
+#define MT9V022_TOTAL_SHUTTER_WIDTH    0x0b
+#define MT9V022_RESET                  0x0c
+#define MT9V022_READ_MODE              0x0d
+#define MT9V022_MONITOR_MODE           0x0e
+#define MT9V022_PIXEL_OPERATION_MODE   0x0f
+#define MT9V022_LED_OUT_CONTROL                0x1b
+#define MT9V022_ADC_MODE_CONTROL       0x1c
+#define MT9V022_ANALOG_GAIN            0x34
+#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
+#define MT9V022_PIXCLK_FV_LV           0x74
+#define MT9V022_DIGITAL_TEST_PATTERN   0x7f
+#define MT9V022_AEC_AGC_ENABLE         0xAF
+#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH        0xBD
+
+/* Progressive scan, master, defaults */
+#define MT9V022_CHIP_CONTROL_DEFAULT   0x188
+
+static const struct soc_camera_data_format mt9v022_colour_formats[] = {
+       /* Order important: first natively supported,
+        * second supported with a GPIO extender */
+       {
+               .name           = "Bayer (sRGB) 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_SBGGR16,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }, {
+               .name           = "Bayer (sRGB) 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+       }
+};
+
+static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
+       /* Order important - see above */
+       {
+               .name           = "Monochrome 10 bit",
+               .depth          = 10,
+               .fourcc         = V4L2_PIX_FMT_Y16,
+       }, {
+               .name           = "Monochrome 8 bit",
+               .depth          = 8,
+               .fourcc         = V4L2_PIX_FMT_GREY,
+       },
+};
+
+struct mt9v022 {
+       struct i2c_client *client;
+       struct soc_camera_device icd;
+       int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+       int switch_gpio;
+       u16 chip_control;
+       unsigned char datawidth;
+};
+
+static int reg_read(struct soc_camera_device *icd, const u8 reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       struct i2c_client *client = mt9v022->client;
+       s32 data = i2c_smbus_read_word_data(client, reg);
+       return data < 0 ? data : swab16(data);
+}
+
+static int reg_write(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
+}
+
+static int reg_set(struct soc_camera_device *icd, const u8 reg,
+                  const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret | data);
+}
+
+static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+                    const u16 data)
+{
+       int ret;
+
+       ret = reg_read(icd, reg);
+       if (ret < 0)
+               return ret;
+       return reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9v022_init(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       int ret;
+
+       /* Almost the default mode: master, parallel, simultaneous, and an
+        * undocumented bit 0x200, which is present in table 7, but not in 8,
+        * plus snapshot mode to disable scan for now */
+       mt9v022->chip_control |= 0x10;
+       ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+       if (ret >= 0)
+               reg_write(icd, MT9V022_READ_MODE, 0x300);
+
+       /* All defaults */
+       if (ret >= 0)
+               /* AEC, AGC on */
+               ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+       if (ret >= 0)
+               /* default - auto */
+               ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
+
+       return ret >= 0 ? 0 : -EIO;
+}
+
+static int mt9v022_release(struct soc_camera_device *icd)
+{
+       /* Nothing? */
+       return 0;
+}
+
+static int mt9v022_start_capture(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       /* Switch to master "normal" mode */
+       mt9v022->chip_control &= ~0x10;
+       if (reg_write(icd, MT9V022_CHIP_CONTROL,
+                     mt9v022->chip_control) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int mt9v022_stop_capture(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       /* Switch to snapshot mode */
+       mt9v022->chip_control |= 0x10;
+       if (reg_write(icd, MT9V022_CHIP_CONTROL,
+                     mt9v022->chip_control) < 0)
+               return -EIO;
+       return 0;
+}
+
+static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       int ret;
+       unsigned int gpio = icl->gpio;
+
+       if (gpio_is_valid(gpio)) {
+               /* We have a data bus switch. */
+               ret = gpio_request(gpio, "mt9v022");
+               if (ret < 0) {
+                       dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
+                       return ret;
+               }
+
+               ret = gpio_direction_output(gpio, 0);
+               if (ret < 0) {
+                       dev_err(&mt9v022->client->dev,
+                               "Cannot set GPIO %u to output\n", gpio);
+                       gpio_free(gpio);
+                       return ret;
+               }
+       }
+
+       mt9v022->switch_gpio = gpio;
+#else
+       mt9v022->switch_gpio = -EINVAL;
+#endif
+       return 0;
+}
+
+static void bus_switch_release(struct mt9v022 *mt9v022)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       if (gpio_is_valid(mt9v022->switch_gpio))
+               gpio_free(mt9v022->switch_gpio);
+#endif
+}
+
+static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       if (!gpio_is_valid(mt9v022->switch_gpio))
+               return -ENODEV;
+
+       gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static int bus_switch_possible(struct mt9v022 *mt9v022)
+{
+#ifdef CONFIG_MT9V022_PCA9536_SWITCH
+       return gpio_is_valid(mt9v022->switch_gpio);
+#else
+       return 0;
+#endif
+}
+
+static int mt9v022_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
+       int ret;
+       u16 pixclk = 0;
+
+       /* Only one width bit may be set */
+       if (!is_power_of_2(width_flag))
+               return -EINVAL;
+
+       if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
+           (mt9v022->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
+           (mt9v022->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
+               /* Well, we actually only can do 10 or 8 bits... */
+               if (width_flag == SOCAM_DATAWIDTH_9)
+                       return -EINVAL;
+
+               ret = bus_switch_act(mt9v022,
+                                    width_flag == SOCAM_DATAWIDTH_8);
+               if (ret < 0)
+                       return ret;
+
+               mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
+       }
+
+       if (flags & SOCAM_PCLK_SAMPLE_RISING)
+               pixclk |= 0x10;
+
+       if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
+               pixclk |= 0x1;
+
+       if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
+               pixclk |= 0x2;
+
+       ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
+       if (ret < 0)
+               return ret;
+
+       if (!(flags & SOCAM_MASTER))
+               mt9v022->chip_control &= ~0x8;
+
+       ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
+               pixclk, mt9v022->chip_control);
+
+       return 0;
+}
+
+static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       unsigned int width_flag = SOCAM_DATAWIDTH_10;
+
+       if (bus_switch_possible(mt9v022))
+               width_flag |= SOCAM_DATAWIDTH_8;
+
+       return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
+               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
+               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
+               SOCAM_MASTER | SOCAM_SLAVE |
+               width_flag;
+}
+
+static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
+               __u32 pixfmt, struct v4l2_rect *rect)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       int ret;
+
+       /* The caller provides a supported format, as verified per call to
+        * icd->try_fmt_cap(), datawidth is from our supported format list */
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y16:
+               if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
+                       return -EINVAL;
+               break;
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SBGGR16:
+               if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
+                       return -EINVAL;
+               break;
+       case 0:
+               /* No format change, only geometry */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Like in example app. Contradicts the datasheet though */
+       ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+       if (ret >= 0) {
+               if (ret & 1) /* Autoexposure */
+                       ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+                                       rect->height + icd->y_skip_top + 43);
+               else
+                       ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+                                       rect->height + icd->y_skip_top + 43);
+       }
+       /* Setup frame format: defaults apart from width and height */
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_ROW_START, rect->top);
+       if (ret >= 0)
+               /* Default 94, Phytec driver says:
+                * "width + horizontal blank >= 660" */
+               ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
+                               rect->width > 660 - 43 ? 43 :
+                               660 - rect->width);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
+       if (ret >= 0)
+               ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
+                               rect->height + icd->y_skip_top);
+
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height);
+
+       return 0;
+}
+
+static int mt9v022_try_fmt_cap(struct soc_camera_device *icd,
+                              struct v4l2_format *f)
+{
+       if (f->fmt.pix.height < 32 + icd->y_skip_top)
+               f->fmt.pix.height = 32 + icd->y_skip_top;
+       if (f->fmt.pix.height > 480 + icd->y_skip_top)
+               f->fmt.pix.height = 480 + icd->y_skip_top;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 752)
+               f->fmt.pix.width = 752;
+       f->fmt.pix.width &= ~0x03; /* ? */
+
+       return 0;
+}
+
+static int mt9v022_get_chip_id(struct soc_camera_device *icd,
+                              struct v4l2_chip_ident *id)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       id->ident       = mt9v022->model;
+       id->revision    = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v022_get_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       reg->val = reg_read(icd, reg->reg);
+
+       if (reg->val > 0xffff)
+               return -EIO;
+
+       return 0;
+}
+
+static int mt9v022_set_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9v022->client->addr)
+               return -ENODEV;
+
+       if (reg_write(icd, reg->reg, reg->val) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+const struct v4l2_queryctrl mt9v022_controls[] = {
+       {
+               .id             = V4L2_CID_VFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Vertically",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_HFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Horizontally",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_GAIN,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Analog Gain",
+               .minimum        = 64,
+               .maximum        = 127,
+               .step           = 1,
+               .default_value  = 64,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Exposure",
+               .minimum        = 1,
+               .maximum        = 255,
+               .step           = 1,
+               .default_value  = 255,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_AUTOGAIN,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Gain",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }, {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Automatic Exposure",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }
+};
+
+static int mt9v022_video_probe(struct soc_camera_device *);
+static void mt9v022_video_remove(struct soc_camera_device *);
+static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
+static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
+
+static struct soc_camera_ops mt9v022_ops = {
+       .owner                  = THIS_MODULE,
+       .probe                  = mt9v022_video_probe,
+       .remove                 = mt9v022_video_remove,
+       .init                   = mt9v022_init,
+       .release                = mt9v022_release,
+       .start_capture          = mt9v022_start_capture,
+       .stop_capture           = mt9v022_stop_capture,
+       .set_fmt_cap            = mt9v022_set_fmt_cap,
+       .try_fmt_cap            = mt9v022_try_fmt_cap,
+       .set_bus_param          = mt9v022_set_bus_param,
+       .query_bus_param        = mt9v022_query_bus_param,
+       .controls               = mt9v022_controls,
+       .num_controls           = ARRAY_SIZE(mt9v022_controls),
+       .get_control            = mt9v022_get_control,
+       .set_control            = mt9v022_set_control,
+       .get_chip_id            = mt9v022_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .get_register           = mt9v022_get_register,
+       .set_register           = mt9v022_set_register,
+#endif
+};
+
+static int mt9v022_get_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       int data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               data = reg_read(icd, MT9V022_READ_MODE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x10);
+               break;
+       case V4L2_CID_HFLIP:
+               data = reg_read(icd, MT9V022_READ_MODE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x20);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x1);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & 0x2);
+               break;
+       }
+       return 0;
+}
+
+static int mt9v022_set_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       int data;
+       const struct v4l2_queryctrl *qctrl;
+
+       qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
+
+       if (!qctrl)
+               return -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_READ_MODE, 0x10);
+               else
+                       data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_HFLIP:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_READ_MODE, 0x20);
+               else
+                       data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_GAIN:
+               /* mt9v022 has minimum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       /* Datasheet says 16 to 64. autogain only works properly
+                        * after setting gain to maximum 14. Larger values
+                        * produce "white fly" noise effect. On the whole,
+                        * manually setting analog gain does no good. */
+                       unsigned long gain = ((ctrl->value - qctrl->minimum) *
+                                             10 + range / 2) / range + 4;
+                       if (gain >= 32)
+                               gain &= ~1;
+                       /* The user wants to set gain manually, hope, she
+                        * knows, what she's doing... Switch AGC off. */
+
+                       if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+                               return -EIO;
+
+                       dev_info(&icd->dev, "Setting gain from %d to %lu\n",
+                                reg_read(icd, MT9V022_ANALOG_GAIN), gain);
+                       if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
+                               return -EIO;
+                       icd->gain = ctrl->value;
+               }
+               break;
+       case V4L2_CID_EXPOSURE:
+               /* mt9v022 has maximum == default */
+               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
+                       return -EINVAL;
+               else {
+                       unsigned long range = qctrl->maximum - qctrl->minimum;
+                       unsigned long shutter = ((ctrl->value - qctrl->minimum) *
+                                                479 + range / 2) / range + 1;
+                       /* The user wants to set shutter width manually, hope,
+                        * she knows, what she's doing... Switch AEC off. */
+
+                       if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+                               return -EIO;
+
+                       dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
+                               reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
+                               shutter);
+                       if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+                                     shutter) < 0)
+                               return -EIO;
+                       icd->exposure = ctrl->value;
+               }
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+               else
+                       data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+               if (data < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->value)
+                       data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+               else
+                       data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+               if (data < 0)
+                       return -EIO;
+               break;
+       }
+       return 0;
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int mt9v022_video_probe(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       s32 data;
+       int ret;
+
+       if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       /* Read out the chip version register */
+       data = reg_read(icd, MT9V022_CHIP_VERSION);
+
+       /* must be 0x1311 or 0x1313 */
+       if (data != 0x1311 && data != 0x1313) {
+               ret = -ENODEV;
+               dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n",
+                        data);
+               goto ei2c;
+       }
+
+       /* Soft reset */
+       ret = reg_write(icd, MT9V022_RESET, 1);
+       if (ret < 0)
+               goto ei2c;
+       /* 15 clock cycles */
+       udelay(200);
+       if (reg_read(icd, MT9V022_RESET)) {
+               dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
+               goto ei2c;
+       }
+
+       /* Set monochrome or colour sensor type */
+       if (sensor_type && (!strcmp("colour", sensor_type) ||
+                           !strcmp("color", sensor_type))) {
+               ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+               mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
+               icd->formats = mt9v022_colour_formats;
+               if (mt9v022->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
+               else
+                       icd->num_formats = 1;
+       } else {
+               ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+               mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
+               icd->formats = mt9v022_monochrome_formats;
+               if (mt9v022->client->dev.platform_data)
+                       icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
+               else
+                       icd->num_formats = 1;
+       }
+
+       if (ret >= 0)
+               ret = soc_camera_video_start(icd);
+       if (ret < 0)
+               goto eisis;
+
+       dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
+                data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
+                "monochrome" : "colour");
+
+       return 0;
+
+eisis:
+ei2c:
+       return ret;
+}
+
+static void mt9v022_video_remove(struct soc_camera_device *icd)
+{
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+
+       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
+               mt9v022->icd.dev.parent, mt9v022->icd.vdev);
+       soc_camera_video_stop(&mt9v022->icd);
+}
+
+static int mt9v022_probe(struct i2c_client *client)
+{
+       struct mt9v022 *mt9v022;
+       struct soc_camera_device *icd;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_link *icl = client->dev.platform_data;
+       int ret;
+
+       if (!icl) {
+               dev_err(&client->dev, "MT9V022 driver needs platform data\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+               return -EIO;
+       }
+
+       mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
+       if (!mt9v022)
+               return -ENOMEM;
+
+       mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
+       mt9v022->client = client;
+       i2c_set_clientdata(client, mt9v022);
+
+       icd = &mt9v022->icd;
+       icd->ops        = &mt9v022_ops;
+       icd->control    = &client->dev;
+       icd->x_min      = 1;
+       icd->y_min      = 4;
+       icd->x_current  = 1;
+       icd->y_current  = 4;
+       icd->width_min  = 48;
+       icd->width_max  = 752;
+       icd->height_min = 32;
+       icd->height_max = 480;
+       icd->y_skip_top = 1;
+       icd->iface      = icl->bus_id;
+       /* Default datawidth - this is the only width this camera (normally)
+        * supports. It is only with extra logic that it can support
+        * other widths. Therefore it seems to be a sensible default. */
+       mt9v022->datawidth = 10;
+
+       ret = bus_switch_request(mt9v022, icl);
+       if (ret)
+               goto eswinit;
+
+       ret = soc_camera_device_register(icd);
+       if (ret)
+               goto eisdr;
+
+       return 0;
+
+eisdr:
+       bus_switch_release(mt9v022);
+eswinit:
+       kfree(mt9v022);
+       return ret;
+}
+
+static int mt9v022_remove(struct i2c_client *client)
+{
+       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+
+       soc_camera_device_unregister(&mt9v022->icd);
+       bus_switch_release(mt9v022);
+       kfree(mt9v022);
+
+       return 0;
+}
+
+static struct i2c_driver mt9v022_i2c_driver = {
+       .driver = {
+               .name = "mt9v022",
+       },
+       .probe          = mt9v022_probe,
+       .remove         = mt9v022_remove,
+};
+
+static int __init mt9v022_mod_init(void)
+{
+       return i2c_add_driver(&mt9v022_i2c_driver);
+}
+
+static void __exit mt9v022_mod_exit(void)
+{
+       i2c_del_driver(&mt9v022_i2c_driver);
+}
+
+module_init(mt9v022_mod_init);
+module_exit(mt9v022_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index cb5a510f9251b49f5e1a9ccfecf0d386b7e80c0b..f68e91fbe7fbcbe7d6e28705a00100eb4c57c06f 100644 (file)
@@ -38,7 +38,7 @@
 #define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
 
 /* global variable */
-static int mxb_num = 0;
+static int mxb_num;
 
 /* initial frequence the tuner will be tuned to.
    in verden (lower saxony, germany) 4148 is a
@@ -47,7 +47,7 @@ static int freq = 4148;
 module_param(freq, int, 0644);
 MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
index 6590058e8ff00ee8ce4acf1028538e2e3e79572b..eafb0c7736e630bff974b002db478702aeee5100 100644 (file)
@@ -4659,7 +4659,9 @@ static const struct file_operations ov511_fops = {
        .read =         ov51x_v4l1_read,
        .mmap =         ov51x_v4l1_mmap,
        .ioctl =        ov51x_v4l1_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 
@@ -5831,7 +5833,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
 
        memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
-       ov->vdev->dev = &dev->dev;
+       ov->vdev->dev = &intf->dev;
        video_set_drvdata(ov->vdev, ov);
 
        for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
index 18c64222dd11f7f4a38bab979165085e2863bf2f..1010e51189b77bd3f6d2970bd69111659e84e51a 100644 (file)
@@ -12,7 +12,7 @@
 #ifdef OV511_DEBUG
        #define PDEBUG(level, fmt, args...) \
                if (debug >= (level)) info("[%s:%d] " fmt, \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
index 50c7763d44b3cad08799299a9f46c2f3839be43c..9afa4fe47726011f4e78edb87fd97095d3410c35 100644 (file)
@@ -24,11 +24,11 @@ extern int ovcamchip_debug;
 
 #define PDEBUG(level, fmt, args...) \
        if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 
 #define DDEBUG(level, dev, fmt, args...) \
        if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \
-               __FUNCTION__, __LINE__ , ## args)
+               __func__, __LINE__ , ## args)
 
 /* Number of times to retry chip detection. Increase this if you are getting
  * "Failed to init camera chip" */
index 6820c2aabd303affccde30951bd018bc7f1d5673..51b1461d8fb62707f48482a59ee34cef55d85a50 100644 (file)
@@ -57,11 +57,11 @@ struct i2c_info
        u8 hits;
 };
 
-static int i2c_count           = 0;
+static int i2c_count;
 static struct i2c_info i2cinfo[64];
 
 static int decoder             = PHILIPS2;
-static int standard            = 0;    /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+static int standard;   /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
 
 /*
  *     I/O ports and Shared Memory
@@ -885,7 +885,9 @@ static const struct file_operations pms_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = pms_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = pms_read,
        .llseek         = no_llseek,
 };
index 6fc1b8be1a1ff7811e458d2c4128876ddc974ad7..a8da90f69dd91eba11285efcf2d706839a40791b 100644 (file)
@@ -58,6 +58,30 @@ config VIDEO_PVRUSB2_SYSFS
 
          Note: This feature is experimental and subject to change.
 
+config VIDEO_PVRUSB2_DVB
+       bool "pvrusb2 DVB support (EXPERIMENTAL)"
+       default n
+       depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+       select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+       ---help---
+
+         This option enables compilation of a DVB interface for the
+         pvrusb2 driver.  Currently this is very very experimental.
+         It is also limiting - the DVB interface can only access the
+         digital side of hybrid devices, and there are going to be
+         issues if you attempt to mess with the V4L side at the same
+         time.  Don't turn this on unless you know what you are
+         doing.
+
+         If you are in doubt, say N.
+
+         Note: This feature is very experimental and might break
+
 config VIDEO_PVRUSB2_DEBUGIFC
        bool "pvrusb2 debug interface"
        depends on VIDEO_PVRUSB2_SYSFS
index 47284e55864808a12be78b854b99cf7946c3a577..5b3083c89aa9bcd1841c41d76c029d3ae682d4dc 100644 (file)
@@ -1,5 +1,6 @@
 obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
 obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
 
 pvrusb2-objs   := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
@@ -9,6 +10,11 @@ pvrusb2-objs  := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
                   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
                   pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
+                  $(obj-pvrusb2-dvb-y) \
                   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
 
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 160437b21e6d3457490f2bd30dc9fdeed82d01b7..b5db6a5bab31e94b5338feb1b788ee14b129eb6e 100644 (file)
 #include "pvrusb2-ioread.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-debug.h"
+#include <linux/wait.h>
+#include <linux/kthread.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 
+static struct pvr2_context *pvr2_context_exist_first;
+static struct pvr2_context *pvr2_context_exist_last;
+static struct pvr2_context *pvr2_context_notify_first;
+static struct pvr2_context *pvr2_context_notify_last;
+static DEFINE_MUTEX(pvr2_context_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
+static int pvr2_context_cleanup_flag;
+static int pvr2_context_cleaned_flag;
+static struct task_struct *pvr2_context_thread_ptr;
+
+
+static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
+{
+       int signal_flag = 0;
+       mutex_lock(&pvr2_context_mutex);
+       if (fl) {
+               if (!mp->notify_flag) {
+                       signal_flag = (pvr2_context_notify_first == NULL);
+                       mp->notify_prev = pvr2_context_notify_last;
+                       mp->notify_next = NULL;
+                       pvr2_context_notify_last = mp;
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp;
+                       } else {
+                               pvr2_context_notify_first = mp;
+                       }
+                       mp->notify_flag = !0;
+               }
+       } else {
+               if (mp->notify_flag) {
+                       mp->notify_flag = 0;
+                       if (mp->notify_next) {
+                               mp->notify_next->notify_prev = mp->notify_prev;
+                       } else {
+                               pvr2_context_notify_last = mp->notify_prev;
+                       }
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp->notify_next;
+                       } else {
+                               pvr2_context_notify_first = mp->notify_next;
+                       }
+               }
+       }
+       mutex_unlock(&pvr2_context_mutex);
+       if (signal_flag) wake_up(&pvr2_context_sync_data);
+}
+
 
 static void pvr2_context_destroy(struct pvr2_context *mp)
 {
-       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
        if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+       pvr2_context_set_notify(mp, 0);
+       mutex_lock(&pvr2_context_mutex);
+       if (mp->exist_next) {
+               mp->exist_next->exist_prev = mp->exist_prev;
+       } else {
+               pvr2_context_exist_last = mp->exist_prev;
+       }
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp->exist_next;
+       } else {
+               pvr2_context_exist_first = mp->exist_next;
+       }
+       if (!pvr2_context_exist_first) {
+               /* Trigger wakeup on control thread in case it is waiting
+                  for an exit condition. */
+               wake_up(&pvr2_context_sync_data);
+       }
+       mutex_unlock(&pvr2_context_mutex);
        kfree(mp);
 }
 
 
-static void pvr2_context_state_check(struct pvr2_context *mp)
+static void pvr2_context_notify(struct pvr2_context *mp)
 {
-       if (mp->init_flag) return;
+       pvr2_context_set_notify(mp,!0);
+}
+
 
-       switch (pvr2_hdw_get_state(mp->hdw)) {
-       case PVR2_STATE_WARM: break;
-       case PVR2_STATE_ERROR: break;
-       case PVR2_STATE_READY: break;
-       case PVR2_STATE_RUN: break;
-       default: return;
+static void pvr2_context_check(struct pvr2_context *mp)
+{
+       struct pvr2_channel *ch1, *ch2;
+       pvr2_trace(PVR2_TRACE_CTXT,
+                  "pvr2_context %p (notify)", mp);
+       if (!mp->initialized_flag && !mp->disconnect_flag) {
+               mp->initialized_flag = !0;
+               pvr2_trace(PVR2_TRACE_CTXT,
+                          "pvr2_context %p (initialize)", mp);
+               /* Finish hardware initialization */
+               if (pvr2_hdw_initialize(mp->hdw,
+                                       (void (*)(void *))pvr2_context_notify,
+                                       mp)) {
+                       mp->video_stream.stream =
+                               pvr2_hdw_get_video_stream(mp->hdw);
+                       /* Trigger interface initialization.  By doing this
+                          here initialization runs in our own safe and
+                          cozy thread context. */
+                       if (mp->setup_func) mp->setup_func(mp);
+               } else {
+                       pvr2_trace(PVR2_TRACE_CTXT,
+                                  "pvr2_context %p (thread skipping setup)",
+                                  mp);
+                       /* Even though initialization did not succeed,
+                          we're still going to continue anyway.  We need
+                          to do this in order to await the expected
+                          disconnect (which we will detect in the normal
+                          course of operation). */
+               }
        }
 
-       pvr2_context_enter(mp); do {
-               mp->init_flag = !0;
-               mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
-               if (mp->setup_func) {
-                       mp->setup_func(mp);
+       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+               ch2 = ch1->mc_next;
+               if (ch1->check_func) ch1->check_func(ch1);
+       }
+
+       if (mp->disconnect_flag && !mp->mc_first) {
+               /* Go away... */
+               pvr2_context_destroy(mp);
+               return;
+       }
+}
+
+
+static int pvr2_context_shutok(void)
+{
+       return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
+}
+
+
+static int pvr2_context_thread_func(void *foo)
+{
+       struct pvr2_context *mp;
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
+
+       do {
+               while ((mp = pvr2_context_notify_first) != NULL) {
+                       pvr2_context_set_notify(mp, 0);
+                       pvr2_context_check(mp);
                }
-       } while (0); pvr2_context_exit(mp);
- }
+               wait_event_interruptible(
+                       pvr2_context_sync_data,
+                       ((pvr2_context_notify_first != NULL) ||
+                        pvr2_context_shutok()));
+       } while (!pvr2_context_shutok());
+
+       pvr2_context_cleaned_flag = !0;
+       wake_up(&pvr2_context_cleanup_data);
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
+
+       wait_event_interruptible(
+               pvr2_context_sync_data,
+               kthread_should_stop());
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
+
+       return 0;
+}
+
+
+int pvr2_context_global_init(void)
+{
+       pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
+                                             0,
+                                             "pvrusb2-context");
+       return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
+}
+
+
+void pvr2_context_global_done(void)
+{
+       pvr2_context_cleanup_flag = !0;
+       wake_up(&pvr2_context_sync_data);
+       wait_event_interruptible(
+               pvr2_context_cleanup_data,
+               pvr2_context_cleaned_flag);
+       kthread_stop(pvr2_context_thread_ptr);
+}
 
 
 struct pvr2_context *pvr2_context_create(
@@ -66,67 +220,75 @@ struct pvr2_context *pvr2_context_create(
        struct pvr2_context *mp = NULL;
        mp = kzalloc(sizeof(*mp),GFP_KERNEL);
        if (!mp) goto done;
-       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
        mp->setup_func = setup_func;
        mutex_init(&mp->mutex);
+       mutex_lock(&pvr2_context_mutex);
+       mp->exist_prev = pvr2_context_exist_last;
+       mp->exist_next = NULL;
+       pvr2_context_exist_last = mp;
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp;
+       } else {
+               pvr2_context_exist_first = mp;
+       }
+       mutex_unlock(&pvr2_context_mutex);
        mp->hdw = pvr2_hdw_create(intf,devid);
        if (!mp->hdw) {
                pvr2_context_destroy(mp);
                mp = NULL;
                goto done;
        }
-       pvr2_hdw_set_state_callback(mp->hdw,
-                                   (void (*)(void *))pvr2_context_state_check,
-                                   mp);
-       pvr2_context_state_check(mp);
+       pvr2_context_set_notify(mp, !0);
  done:
        return mp;
 }
 
 
-void pvr2_context_enter(struct pvr2_context *mp)
+static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
+{
+       unsigned int tmsk,mmsk;
+       struct pvr2_channel *cp;
+       struct pvr2_hdw *hdw = mp->hdw;
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       tmsk = mmsk;
+       for (cp = mp->mc_first; cp; cp = cp->mc_next) {
+               if (!cp->input_mask) continue;
+               tmsk &= cp->input_mask;
+       }
+       pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
+       pvr2_hdw_commit_ctl(hdw);
+}
+
+
+static void pvr2_context_enter(struct pvr2_context *mp)
 {
        mutex_lock(&mp->mutex);
-       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
 }
 
 
-void pvr2_context_exit(struct pvr2_context *mp)
+static void pvr2_context_exit(struct pvr2_context *mp)
 {
        int destroy_flag = 0;
        if (!(mp->mc_first || !mp->disconnect_flag)) {
                destroy_flag = !0;
        }
-       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
        mutex_unlock(&mp->mutex);
-       if (destroy_flag) pvr2_context_destroy(mp);
-}
-
-
-static void pvr2_context_run_checks(struct pvr2_context *mp)
-{
-       struct pvr2_channel *ch1,*ch2;
-       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
-               ch2 = ch1->mc_next;
-               if (ch1->check_func) {
-                       ch1->check_func(ch1);
-               }
-       }
+       if (destroy_flag) pvr2_context_notify(mp);
 }
 
 
 void pvr2_context_disconnect(struct pvr2_context *mp)
 {
-       pvr2_context_enter(mp); do {
-               pvr2_hdw_disconnect(mp->hdw);
-               mp->disconnect_flag = !0;
-               pvr2_context_run_checks(mp);
-       } while (0); pvr2_context_exit(mp);
+       pvr2_hdw_disconnect(mp->hdw);
+       mp->disconnect_flag = !0;
+       pvr2_context_notify(mp);
 }
 
 
 void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
 {
+       pvr2_context_enter(mp);
        cp->hdw = mp->hdw;
        cp->mc_head = mp;
        cp->mc_next = NULL;
@@ -137,6 +299,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
                mp->mc_first = cp;
        }
        mp->mc_last = cp;
+       pvr2_context_exit(mp);
 }
 
 
@@ -152,7 +315,10 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
 void pvr2_channel_done(struct pvr2_channel *cp)
 {
        struct pvr2_context *mp = cp->mc_head;
+       pvr2_context_enter(mp);
+       cp->input_mask = 0;
        pvr2_channel_disclaim_stream(cp);
+       pvr2_context_reset_input_limits(mp);
        if (cp->mc_next) {
                cp->mc_next->mc_prev = cp->mc_prev;
        } else {
@@ -164,6 +330,58 @@ void pvr2_channel_done(struct pvr2_channel *cp)
                mp->mc_first = cp->mc_next;
        }
        cp->hdw = NULL;
+       pvr2_context_exit(mp);
+}
+
+
+int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
+{
+       unsigned int tmsk,mmsk;
+       int ret = 0;
+       struct pvr2_channel *p2;
+       struct pvr2_hdw *hdw = cp->hdw;
+
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       cmsk &= mmsk;
+       if (cmsk == cp->input_mask) {
+               /* No change; nothing to do */
+               return 0;
+       }
+
+       pvr2_context_enter(cp->mc_head);
+       do {
+               if (!cmsk) {
+                       cp->input_mask = 0;
+                       pvr2_context_reset_input_limits(cp->mc_head);
+                       break;
+               }
+               tmsk = mmsk;
+               for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
+                       if (p2 == cp) continue;
+                       if (!p2->input_mask) continue;
+                       tmsk &= p2->input_mask;
+               }
+               if (!(tmsk & cmsk)) {
+                       ret = -EPERM;
+                       break;
+               }
+               tmsk &= cmsk;
+               if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
+                       /* Internal failure changing allowed list; probably
+                          should not happen, but react if it does. */
+                       break;
+               }
+               cp->input_mask = cmsk;
+               pvr2_hdw_commit_ctl(hdw);
+       } while (0);
+       pvr2_context_exit(cp->mc_head);
+       return ret;
+}
+
+
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
+{
+       return cp->input_mask;
 }
 
 
@@ -173,7 +391,7 @@ int pvr2_channel_claim_stream(struct pvr2_channel *cp,
        int code = 0;
        pvr2_context_enter(cp->mc_head); do {
                if (sp == cp->stream) break;
-               if (sp->user) {
+               if (sp && sp->user) {
                        code = -EBUSY;
                        break;
                }
index a04187a932251dd86b11020916f55c31c3da51c5..745e270233c26572f2c8f647ae64b43b24908268 100644 (file)
@@ -30,7 +30,6 @@ struct pvr2_stream;  /* stream interface - defined elsewhere */
 struct pvr2_context;        /* All central state */
 struct pvr2_channel;        /* One I/O pathway to a user */
 struct pvr2_context_stream; /* Wrapper for a stream */
-struct pvr2_crit_reg;       /* Critical region pointer */
 struct pvr2_ioread;         /* Low level stream structure */
 
 struct pvr2_context_stream {
@@ -41,11 +40,16 @@ struct pvr2_context_stream {
 struct pvr2_context {
        struct pvr2_channel *mc_first;
        struct pvr2_channel *mc_last;
+       struct pvr2_context *exist_next;
+       struct pvr2_context *exist_prev;
+       struct pvr2_context *notify_next;
+       struct pvr2_context *notify_prev;
        struct pvr2_hdw *hdw;
        struct pvr2_context_stream video_stream;
        struct mutex mutex;
+       int notify_flag;
+       int initialized_flag;
        int disconnect_flag;
-       int init_flag;
 
        /* Called after pvr2_context initialization is complete */
        void (*setup_func)(struct pvr2_context *);
@@ -58,12 +62,10 @@ struct pvr2_channel {
        struct pvr2_channel *mc_prev;
        struct pvr2_context_stream *stream;
        struct pvr2_hdw *hdw;
+       unsigned int input_mask;
        void (*check_func)(struct pvr2_channel *);
 };
 
-void pvr2_context_enter(struct pvr2_context *);
-void pvr2_context_exit(struct pvr2_context *);
-
 struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
                                         const struct usb_device_id *devid,
                                         void (*setup_func)(struct pvr2_context *));
@@ -71,11 +73,15 @@ void pvr2_context_disconnect(struct pvr2_context *);
 
 void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
 void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
 int pvr2_channel_claim_stream(struct pvr2_channel *,
                              struct pvr2_context_stream *);
 struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
        struct pvr2_context_stream *);
 
+int pvr2_context_global_init(void);
+void pvr2_context_global_done(void);
 
 #endif /* __PVRUSB2_CONTEXT_H */
 /*
index 5a3e8d21a38ae7e95b58cd4940a4b905186928d5..91a42f2473a7ff7718d163233c38e39b3efd3b5f 100644 (file)
@@ -30,6 +30,9 @@ static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
 {
        if (cptr->info->check_value) {
                if (!cptr->info->check_value(cptr,val)) return -ERANGE;
+       } else if (cptr->info->type == pvr2_ctl_enum) {
+               if (val < 0) return -ERANGE;
+               if (val >= cptr->info->def.type_enum.count) return -ERANGE;
        } else {
                int lim;
                lim = cptr->info->def.type_int.min_value;
@@ -63,13 +66,10 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
                if (cptr->info->set_value) {
                        if (cptr->info->type == pvr2_ctl_bitmask) {
                                mask &= cptr->info->def.type_bitmask.valid_bits;
-                       } else if (cptr->info->type == pvr2_ctl_int) {
+                       } else if ((cptr->info->type == pvr2_ctl_int)||
+                                  (cptr->info->type == pvr2_ctl_enum)) {
                                ret = pvr2_ctrl_range_check(cptr,val);
                                if (ret < 0) break;
-                       } else if (cptr->info->type == pvr2_ctl_enum) {
-                               if (val >= cptr->info->def.type_enum.count) {
-                                       break;
-                               }
                        } else if (cptr->info->type != pvr2_ctl_bool) {
                                break;
                        }
@@ -204,8 +204,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
                if (cptr->info->type == pvr2_ctl_enum) {
                        const char **names;
                        names = cptr->info->def.type_enum.value_names;
-                       if ((val >= 0) &&
-                           (val < cptr->info->def.type_enum.count)) {
+                       if (pvr2_ctrl_range_check(cptr,val) == 0) {
                                if (names[val]) {
                                        *blen = scnprintf(
                                                bptr,bmax,"%s",
@@ -528,10 +527,8 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
                                ptr,len,valptr,
                                cptr->info->def.type_enum.value_names,
                                cptr->info->def.type_enum.count);
-                       if ((ret >= 0) &&
-                           ((*valptr < 0) ||
-                            (*valptr >= cptr->info->def.type_enum.count))) {
-                               ret = -ERANGE;
+                       if (ret >= 0) {
+                               ret = pvr2_ctrl_range_check(cptr,*valptr);
                        }
                        if (maskptr) *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bitmask) {
index ffdc45c324e5d24936de4557da279af46314ee8d..97350b048b8deeb394fba59265467215f3930b45 100644 (file)
@@ -84,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = {
                .vid = CX25840_COMPOSITE2,
                .aud = CX25840_AUDIO5,
        },
-       [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
+       [PVR2_CVAL_INPUT_RADIO] = {
+               /* line-in is used for radio and composite.  A GPIO is
+                  used to switch between the two choices. */
                .vid = CX25840_COMPOSITE1,
                .aud = CX25840_AUDIO_SERIAL,
        },
index fca49d8a9311e70544e89b5cd713fc677d91cf05..11537ddf8aa3b0d6b81a44f069b83fb1feec220c 100644 (file)
@@ -39,7 +39,7 @@ extern int pvrusb2_debug;
 #define PVR2_TRACE_EEPROM     (1 << 10) /* eeprom parsing / report */
 #define PVR2_TRACE_STRUCT     (1 << 11) /* internal struct creation */
 #define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
-#define PVR2_TRACE_CREG       (1 << 13) /* Main critical region entry / exit */
+#define PVR2_TRACE_CTXT       (1 << 13) /* Main context tracking */
 #define PVR2_TRACE_SYSFS      (1 << 14) /* Sysfs driven I/O */
 #define PVR2_TRACE_FIRMWARE   (1 << 15) /* firmware upload actions */
 #define PVR2_TRACE_CHIPS      (1 << 16) /* chip broadcast operation */
index b0687430fdd421fc8798ecb4bde590512b42f2d5..b53121c78ff992e9b249e3a1c3afeb8526823ee6 100644 (file)
@@ -164,6 +164,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
        int ccnt;
        int ret;
        u32 gpio_dir,gpio_in,gpio_out;
+       struct pvr2_stream_stats stats;
+       struct pvr2_stream *sp;
 
        ret = pvr2_hdw_is_hsm(hdw);
        ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
@@ -182,6 +184,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
                         pvr2_hdw_get_streaming(hdw) ? "on" : "off");
        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 
+
+       sp = pvr2_hdw_get_video_stream(hdw);
+       if (sp) {
+               pvr2_stream_get_stats(sp, &stats, 0);
+               ccnt = scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u\n",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       }
+
        return bcnt;
 }
 
@@ -220,6 +240,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
                        return pvr2_hdw_cmd_decoder_reset(hdw);
                } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
                        return pvr2_hdw_untrip(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
+                       pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
+                                             NULL, !0);
+                       return 0;
                }
                return -EINVAL;
        } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
index fe9991c10cf4c5b577d9d610360bad84271d11c4..2dd06a90adce435869226611f0864d77ee2f3d65 100644 (file)
@@ -32,7 +32,15 @@ pvr2_device_desc structures.
 /* This is needed in order to pull in tuner type ids... */
 #include <linux/i2c.h>
 #include <media/tuner.h>
-
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-hdw-internal.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "tda8290.h"
+#include "tuner-simple.h"
+#endif
 
 
 /*------------------------------------------------------------------------*/
@@ -49,14 +57,19 @@ static const char *pvr2_fw1_names_29xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_29xxx = {
-               .description = "WinTV PVR USB2 Model Category 29xxxx",
+               .description = "WinTV PVR USB2 Model Category 29xxx",
                .shortname = "29xxx",
                .client_modules.lst = pvr2_client_29xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
                .fx2_firmware.lst = pvr2_fw1_names_29xxx,
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
                .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -75,7 +88,7 @@ static const char *pvr2_fw1_names_24xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_24xxx = {
-               .description = "WinTV PVR USB2 Model Category 24xxxx",
+               .description = "WinTV PVR USB2 Model Category 24xxx",
                .shortname = "24xxx",
                .client_modules.lst = pvr2_client_24xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
@@ -85,7 +98,12 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
                .flag_has_wm8775 = !0,
                .flag_has_hauppauge_rom = !0,
                .flag_has_hauppauge_custom_ir = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -105,6 +123,30 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
                .flag_has_cx25840 = !0,
                .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* GOTVIEW USB2.0 DVD Deluxe */
+
+/* (same module list as gotview_2) */
+
+static const struct pvr2_device_desc pvr2_device_gotview_2d = {
+               .description = "Gotview USB 2.0 DVD Deluxe",
+               .shortname = "gv2d",
+               .client_modules.lst = pvr2_client_gotview_2,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+               .flag_has_cx25840 = !0,
+               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
 };
 
@@ -114,6 +156,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
 /*------------------------------------------------------------------------*/
 /* OnAir Creator */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3303_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3303,
+       .clock_polarity_flip = 1,
+};
+
+static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_LG_TDVS_H06XF);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+       .frontend_attach = pvr2_lgdt3303_attach,
+       .tuner_attach    = pvr2_lgh06xf_attach,
+};
+#endif
+
 static const char *pvr2_client_onair_creator[] = {
        "saa7115",
        "tuner",
@@ -126,7 +200,16 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
                .client_modules.lst = pvr2_client_onair_creator,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
                .default_tuner_type = TUNER_LG_TDVS_H06XF,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_creator_fe_props,
+#endif
 };
 #endif
 
@@ -136,6 +219,37 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
 /*------------------------------------------------------------------------*/
 /* OnAir USB 2.0 */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3302_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3302,
+};
+
+static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_PHILIPS_FCV1236D);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+       .frontend_attach = pvr2_lgdt3302_attach,
+       .tuner_attach    = pvr2_fcv1236d_attach,
+};
+#endif
+
 static const char *pvr2_client_onair_usb2[] = {
        "saa7115",
        "tuner",
@@ -147,8 +261,17 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
                .shortname = "oa2",
                .client_modules.lst = pvr2_client_onair_usb2,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
-               .default_tuner_type = TUNER_PHILIPS_ATSC,
+               .default_tuner_type = TUNER_PHILIPS_FCV1236D,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_usb2_fe_props,
+#endif
 };
 #endif
 
@@ -157,6 +280,50 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 73xxx */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct tda10048_config hauppauge_tda10048_config = {
+       .demod_address  = 0x10 >> 1,
+       .output_mode    = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen = TDA10048_BULKWRITE_50,
+       .inversion      = TDA10048_INVERSION_ON,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda18271_config hauppauge_tda18271_dvb_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_dvb_config);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+       .frontend_attach = pvr2_tda10048_attach,
+       .tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
+};
+#endif
+
 static const char *pvr2_client_73xxx[] = {
        "cx25840",
        "tuner",
@@ -167,7 +334,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
 };
 
 static const struct pvr2_device_desc pvr2_device_73xxx = {
-               .description = "WinTV PVR USB2 Model Category 73xxxx",
+               .description = "WinTV PVR USB2 Model Category 73xxx",
                .shortname = "73xxx",
                .client_modules.lst = pvr2_client_73xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
@@ -175,15 +342,14 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
                .flag_has_cx25840 = !0,
                .flag_has_hauppauge_rom = !0,
-#if 0
                .flag_has_analogtuner = !0,
                .flag_has_composite = !0,
                .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
                .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-#else
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_73xxx_dvb_props,
 #endif
 };
 
@@ -192,6 +358,56 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 75xxx */
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct s5h1409_config pvr2_s5h1409_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .qam_if        = 4000,
+       .inversion     = S5H1409_INVERSION_ON,
+       .status_mode   = S5H1409_DEMODLOCKING,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_config);
+
+       return 0;
+}
+
+struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1409_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
+#endif
+
 static const char *pvr2_client_75xxx[] = {
        "cx25840",
        "tuner",
@@ -201,17 +417,43 @@ static const char *pvr2_fw1_names_75xxx[] = {
                "v4l-pvrusb2-73xxx-01.fw",
 };
 
-static const struct pvr2_device_desc pvr2_device_75xxx = {
-               .description = "WinTV PVR USB2 Model Category 75xxxx",
-               .shortname = "75xxx",
+static const struct pvr2_device_desc pvr2_device_750xx = {
+               .description = "WinTV PVR USB2 Model Category 750xx",
+               .shortname = "750xx",
+               .client_modules.lst = pvr2_client_75xxx,
+               .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+               .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_750xx_dvb_props,
+#endif
+};
+
+static const struct pvr2_device_desc pvr2_device_751xx = {
+               .description = "WinTV PVR USB2 Model Category 751xx",
+               .shortname = "751xx",
                .client_modules.lst = pvr2_client_75xxx,
                .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
                .fx2_firmware.lst = pvr2_fw1_names_75xxx,
                .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
                .flag_has_cx25840 = !0,
                .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
                .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
                .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
 };
 
 
@@ -225,6 +467,8 @@ struct usb_device_id pvr2_device_table[] = {
          .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
        { USB_DEVICE(0x1164, 0x0622),
          .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
+       { USB_DEVICE(0x1164, 0x0602),
+         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
 #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
        { USB_DEVICE(0x11ba, 0x1003),
          .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
@@ -236,9 +480,9 @@ struct usb_device_id pvr2_device_table[] = {
        { USB_DEVICE(0x2040, 0x7300),
          .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
        { USB_DEVICE(0x2040, 0x7500),
-         .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+         .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
        { USB_DEVICE(0x2040, 0x7501),
-         .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+         .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
        { }
 };
 
index 64b467f0637f121e1ea4eb6b9eb9fe8a6be2ef01..c2e2b06fe2e0bbeb80d791309495591e4d75e9da 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <linux/mod_devicetable.h>
 #include <linux/videodev2.h>
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-dvb.h"
+#endif
 
 /*
 
@@ -39,6 +42,13 @@ struct pvr2_string_table {
 #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
 #define PVR2_ROUTING_SCHEME_GOTVIEW 1
 
+#define PVR2_DIGITAL_SCHEME_NONE 0
+#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
+#define PVR2_DIGITAL_SCHEME_ONAIR 2
+
+#define PVR2_LED_SCHEME_NONE 0
+#define PVR2_LED_SCHEME_HAUPPAUGE 1
+
 /* This describes a particular hardware type (except for the USB device ID
    which must live in a separate structure due to environmental
    constraints).  See the top of pvrusb2-hdw.c for where this is
@@ -58,40 +68,64 @@ struct pvr2_device_desc {
           was initialized from internal ROM. */
        struct pvr2_string_table fx2_firmware;
 
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* callback functions to handle attachment of digital tuner & demod */
+       struct pvr2_dvb_props *dvb_props;
+
+#endif
+       /* Initial standard bits to use for this device, if not zero.
+          Anything set here is also implied as an available standard.
+          Note: This is ignored if overridden on the module load line via
+          the video_std module option. */
+       v4l2_std_id default_std_mask;
+
+       /* V4L tuner type ID to use with this device (only used if the
+          driver could not discover the type any other way). */
+       int default_tuner_type;
+
        /* Signal routing scheme used by device, contains one of
           PVR2_ROUTING_SCHEME_XXX.  Schemes have to be defined as we
           encounter them.  This is an arbitrary integer scheme id; its
           meaning is contained entirely within the driver and is
           interpreted by logic which must send commands to the chip-level
           drivers (search for things which touch this field). */
-       unsigned int signal_routing_scheme;
+       unsigned char signal_routing_scheme;
 
-       /* V4L tuner type ID to use with this device (only used if the
-          driver could not discover the type any other way). */
-       int default_tuner_type;
+       /* Indicates scheme for controlling device's LED (if any).  The
+          driver will turn on the LED when streaming is underway.  This
+          contains one of PVR2_LED_SCHEME_XXX. */
+       unsigned char led_scheme;
 
-       /* Initial standard bits to use for this device, if not zero.
-          Anything set here is also implied as an available standard.
-          Note: This is ignored if overridden on the module load line via
-          the video_std module option. */
-       v4l2_std_id default_std_mask;
+       /* Control scheme to use if there is a digital tuner.  This
+          contains one of PVR2_DIGITAL_SCHEME_XXX.  This is an arbitrary
+          integer scheme id; its meaning is contained entirely within the
+          driver and is interpreted by logic which must control the
+          streaming pathway (search for things which touch this field). */
+       unsigned char digital_control_scheme;
 
        /* If set, we don't bother trying to load cx23416 firmware. */
-       char flag_skip_cx23416_firmware;
+       int flag_skip_cx23416_firmware:1;
+
+       /* If set, the encoder must be healthy in order for digital mode to
+          work (otherwise we assume that digital streaming will work even
+          if we fail to locate firmware for the encoder).  If the device
+          doesn't support digital streaming then this flag has no
+          effect. */
+       int flag_digital_requires_cx23416:1;
 
        /* Device has a hauppauge eeprom which we can interrogate. */
-       char flag_has_hauppauge_rom;
+       int flag_has_hauppauge_rom:1;
 
        /* Device does not require a powerup command to be issued. */
-       char flag_no_powerup;
+       int flag_no_powerup:1;
 
        /* Device has a cx25840 - this enables special additional logic to
           handle it. */
-       char flag_has_cx25840;
+       int flag_has_cx25840:1;
 
        /* Device has a wm8775 - this enables special additional logic to
           ensure that it is found. */
-       char flag_has_wm8775;
+       int flag_has_wm8775:1;
 
        /* Device has IR hardware that can be faked into looking like a
           normal Hauppauge i2c IR receiver.  This is currently very
@@ -101,7 +135,15 @@ struct pvr2_device_desc {
           to virtualize the presence of the non-existant IR receiver chip and
           implement the virtual receiver in terms of appropriate FX2
           commands. */
-       char flag_has_hauppauge_custom_ir;
+       int flag_has_hauppauge_custom_ir:1;
+
+       /* These bits define which kinds of sources the device can handle.
+          Note: Digital tuner presence is inferred by the
+          digital_control_scheme enumeration. */
+       int flag_has_fmradio:1;       /* Has FM radio receiver */
+       int flag_has_analogtuner:1;   /* Has analog tuner */
+       int flag_has_composite:1;     /* Has composite input */
+       int flag_has_svideo:1;        /* Has s-video input */
 };
 
 extern struct usb_device_id pvr2_device_table[];
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
new file mode 100644 (file)
index 0000000..2e64f98
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ *  pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
+ *
+ *  Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include "dvbdev.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+       unsigned int count;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream;
+
+       printk(KERN_DEBUG "dvb thread started\n");
+       set_freezable();
+
+       stream = adap->channel.stream->stream;
+
+       for (;;) {
+               if (kthread_should_stop()) break;
+
+               /* Not sure about this... */
+               try_to_freeze();
+
+               bp = pvr2_stream_get_ready_buffer(stream);
+               if (bp != NULL) {
+                       count = pvr2_buffer_get_count(bp);
+                       if (count) {
+                               dvb_dmx_swfilter(
+                                       &adap->demux,
+                                       adap->buffer_storage[
+                                           pvr2_buffer_get_id(bp)],
+                                       count);
+                       } else {
+                               ret = pvr2_buffer_get_status(bp);
+                               if (ret < 0) break;
+                       }
+                       ret = pvr2_buffer_queue(bp);
+                       if (ret < 0) break;
+
+                       /* Since we know we did something to a buffer,
+                          just go back and try again.  No point in
+                          blocking unless we really ran out of
+                          buffers to process. */
+                       continue;
+               }
+
+
+               /* Wait until more buffers become available or we're
+                  told not to wait any longer. */
+               ret = wait_event_interruptible(
+                   adap->buffer_wait_data,
+                   (pvr2_stream_get_ready_count(stream) > 0) ||
+                   kthread_should_stop());
+               if (ret < 0) break;
+       }
+
+       /* If we get here and ret is < 0, then an error has occurred.
+          Probably would be a good idea to communicate that to DVB core... */
+
+       printk(KERN_DEBUG "dvb thread stopped\n");
+
+       return 0;
+}
+
+static int pvr2_dvb_feed_thread(void *data)
+{
+       int stat = pvr2_dvb_feed_func(data);
+       /* from videobuf-dvb.c: */
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+       }
+       return stat;
+}
+
+static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
+{
+       wake_up(&adap->buffer_wait_data);
+}
+
+static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
+{
+       unsigned int idx;
+       struct pvr2_stream *stream;
+
+       if (adap->thread) {
+               kthread_stop(adap->thread);
+               adap->thread = NULL;
+       }
+
+       if (adap->channel.stream) {
+               stream = adap->channel.stream->stream;
+       } else {
+               stream = NULL;
+       }
+       if (stream) {
+               pvr2_hdw_set_streaming(adap->channel.hdw, 0);
+               pvr2_stream_set_callback(stream, NULL, NULL);
+               pvr2_stream_kill(stream);
+               pvr2_stream_set_buffer_count(stream, 0);
+               pvr2_channel_claim_stream(&adap->channel, NULL);
+       }
+
+       if (adap->stream_run) {
+               for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+                       if (!(adap->buffer_storage[idx])) continue;
+                       kfree(adap->buffer_storage[idx]);
+                       adap->buffer_storage[idx] = 0;
+               }
+               adap->stream_run = 0;
+       }
+}
+
+static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_context *pvr = adap->channel.mc_head;
+       unsigned int idx;
+       int ret;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream = 0;
+
+       if (adap->stream_run) return -EIO;
+
+       ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
+       /* somebody else already has the stream */
+       if (ret < 0) return ret;
+
+       stream = adap->channel.stream->stream;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
+                                                   GFP_KERNEL);
+               if (!(adap->buffer_storage[idx])) return -ENOMEM;
+       }
+
+       pvr2_stream_set_callback(pvr->video_stream.stream,
+                                (pvr2_stream_callback) pvr2_dvb_notify, adap);
+
+       ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
+       if (ret < 0) return ret;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               bp = pvr2_stream_get_buffer(stream, idx);
+               pvr2_buffer_set_buffer(bp,
+                                      adap->buffer_storage[idx],
+                                      PVR2_DVB_BUFFER_SIZE);
+       }
+
+       ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
+       if (ret < 0) return ret;
+
+       while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) {
+               ret = pvr2_buffer_queue(bp);
+               if (ret < 0) return ret;
+       }
+
+       adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
+
+       if (IS_ERR(adap->thread)) {
+               ret = PTR_ERR(adap->thread);
+               adap->thread = NULL;
+               return ret;
+       }
+
+       adap->stream_run = !0;
+
+       return 0;
+}
+
+static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
+{
+       int ret = pvr2_dvb_stream_do_start(adap);
+       if (ret < 0) pvr2_dvb_stream_end(adap);
+       return ret;
+}
+
+static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+       struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
+       int ret = 0;
+
+       if (adap == NULL) return -ENODEV;
+
+       mutex_lock(&adap->lock);
+       do {
+               if (onoff) {
+                       if (!adap->feedcount) {
+                               printk(KERN_DEBUG "start feeding\n");
+                               ret = pvr2_dvb_stream_start(adap);
+                               if (ret < 0) break;
+                       }
+                       (adap->feedcount)++;
+               } else if (adap->feedcount > 0) {
+                       (adap->feedcount)--;
+                       if (!adap->feedcount) {
+                               printk(KERN_DEBUG "stop feeding\n");
+                               pvr2_dvb_stream_end(adap);
+                       }
+               }
+       } while (0);
+       mutex_unlock(&adap->lock);
+
+       return ret;
+}
+
+static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
+              dvbdmxfeed->pid, dvbdmxfeed->type);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
+}
+
+static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
+              dvbdmxfeed->pid, dvbdmxfeed->type);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
+}
+
+static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct pvr2_dvb_adapter *adap = fe->dvb->priv;
+       return pvr2_channel_limit_inputs(
+           &adap->channel,
+           (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
+}
+
+static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+
+       ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
+                                  THIS_MODULE/*&hdw->usb_dev->owner*/,
+                                  &adap->channel.hdw->usb_dev->dev,
+                                  adapter_nr);
+       if (ret < 0) {
+               err("dvb_register_adapter failed: error %d", ret);
+               goto err;
+       }
+       adap->dvb_adap.priv = adap;
+
+       adap->demux.dmx.capabilities = DMX_TS_FILTERING |
+                                      DMX_SECTION_FILTERING |
+                                      DMX_MEMORY_BASED_FILTERING;
+       adap->demux.priv             = adap;
+       adap->demux.filternum        = 256;
+       adap->demux.feednum          = 256;
+       adap->demux.start_feed       = pvr2_dvb_start_feed;
+       adap->demux.stop_feed        = pvr2_dvb_stop_feed;
+       adap->demux.write_to_decoder = NULL;
+
+       ret = dvb_dmx_init(&adap->demux);
+       if (ret < 0) {
+               err("dvb_dmx_init failed: error %d", ret);
+               goto err_dmx;
+       }
+
+       adap->dmxdev.filternum       = adap->demux.filternum;
+       adap->dmxdev.demux           = &adap->demux.dmx;
+       adap->dmxdev.capabilities    = 0;
+
+       ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+       if (ret < 0) {
+               err("dvb_dmxdev_init failed: error %d", ret);
+               goto err_dmx_dev;
+       }
+
+       dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+
+       return 0;
+
+err_dmx_dev:
+       dvb_dmx_release(&adap->demux);
+err_dmx:
+       dvb_unregister_adapter(&adap->dvb_adap);
+err:
+       return ret;
+}
+
+static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
+{
+       printk(KERN_DEBUG "unregistering DVB devices\n");
+       dvb_net_release(&adap->dvb_net);
+       adap->demux.dmx.close(&adap->demux.dmx);
+       dvb_dmxdev_release(&adap->dmxdev);
+       dvb_dmx_release(&adap->demux);
+       dvb_unregister_adapter(&adap->dvb_adap);
+       return 0;
+}
+
+static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_hdw *hdw = adap->channel.hdw;
+       struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+       int ret = 0;
+
+       if (dvb_props == NULL) {
+               err("fe_props not defined!");
+               return -EINVAL;
+       }
+
+       ret = pvr2_channel_limit_inputs(
+           &adap->channel,
+           (1 << PVR2_CVAL_INPUT_DTV));
+       if (ret) {
+               err("failed to grab control of dtv input (code=%d)",
+                   ret);
+               return ret;
+       }
+
+       if (dvb_props->frontend_attach == NULL) {
+               err("frontend_attach not defined!");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
+
+               if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
+                       err("frontend registration failed!");
+                       dvb_frontend_detach(adap->fe);
+                       adap->fe = NULL;
+                       ret = -ENODEV;
+                       goto done;
+               }
+
+               if (dvb_props->tuner_attach)
+                       dvb_props->tuner_attach(adap);
+
+               if (adap->fe->ops.analog_ops.standby)
+                       adap->fe->ops.analog_ops.standby(adap->fe);
+
+               /* Ensure all frontends negotiate bus access */
+               adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
+
+       } else {
+               err("no frontend was attached!");
+               ret = -ENODEV;
+               return ret;
+       }
+
+ done:
+       pvr2_channel_limit_inputs(&adap->channel, 0);
+       return ret;
+}
+
+static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
+{
+       if (adap->fe != NULL) {
+               dvb_unregister_frontend(adap->fe);
+               dvb_frontend_detach(adap->fe);
+       }
+       return 0;
+}
+
+static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
+{
+       pvr2_dvb_stream_end(adap);
+       pvr2_dvb_frontend_exit(adap);
+       pvr2_dvb_adapter_exit(adap);
+       pvr2_channel_done(&adap->channel);
+       kfree(adap);
+}
+
+static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_dvb_adapter *adap;
+       adap = container_of(chp, struct pvr2_dvb_adapter, channel);
+       if (!adap->channel.mc_head->disconnect_flag) return;
+       pvr2_dvb_destroy(adap);
+}
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
+{
+       int ret = 0;
+       struct pvr2_dvb_adapter *adap;
+       if (!pvr->hdw->hdw_desc->dvb_props) {
+               /* Device lacks a digital interface so don't set up
+                  the DVB side of the driver either.  For now. */
+               return NULL;
+       }
+       adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+       if (!adap) return adap;
+       pvr2_channel_init(&adap->channel, pvr);
+       adap->channel.check_func = pvr2_dvb_internal_check;
+       init_waitqueue_head(&adap->buffer_wait_data);
+       mutex_init(&adap->lock);
+       ret = pvr2_dvb_adapter_init(adap);
+       if (ret < 0) goto fail1;
+       ret = pvr2_dvb_frontend_init(adap);
+       if (ret < 0) goto fail2;
+       return adap;
+
+fail2:
+       pvr2_dvb_adapter_exit(adap);
+fail1:
+       pvr2_channel_done(&adap->channel);
+       return NULL;
+}
+
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
new file mode 100644 (file)
index 0000000..884ff91
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __PVRUSB2_DVB_H__
+#define __PVRUSB2_DVB_H__
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+#include "pvrusb2-context.h"
+
+#define PVR2_DVB_BUFFER_COUNT 32
+#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_dvb_adapter {
+       struct pvr2_channel     channel;
+
+       struct dvb_adapter      dvb_adap;
+       struct dmxdev           dmxdev;
+       struct dvb_demux        demux;
+       struct dvb_net          dvb_net;
+       struct dvb_frontend     *fe;
+
+       int                     feedcount;
+       int                     max_feed_count;
+
+       struct task_struct      *thread;
+       struct mutex            lock;
+
+       unsigned int            stream_run:1;
+
+       wait_queue_head_t       buffer_wait_data;
+       char                    *buffer_storage[PVR2_DVB_BUFFER_COUNT];
+};
+
+struct pvr2_dvb_props {
+       int (*frontend_attach) (struct pvr2_dvb_adapter *);
+       int (*tuner_attach) (struct pvr2_dvb_adapter *);
+};
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
+
+#endif /* __PVRUSB2_DVB_H__ */
index 64062879981e4297db9f8386c68306c15e61c616..c46d367f7472599ca8b57aeeddd52e2956c372a6 100644 (file)
@@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt,
                        ret = -EBUSY;
                }
                if (ret) {
+                       del_timer_sync(&hdw->encoder_run_timer);
                        hdw->state_encoder_ok = 0;
                        pvr2_trace(PVR2_TRACE_STBITS,
                                   "State bit %s <-- %s",
                                   "state_encoder_ok",
                                   (hdw->state_encoder_ok ? "true" : "false"));
+                       if (hdw->state_encoder_runok) {
+                               hdw->state_encoder_runok = 0;
+                               pvr2_trace(PVR2_TRACE_STBITS,
+                                  "State bit %s <-- %s",
+                                          "state_encoder_runok",
+                                          (hdw->state_encoder_runok ?
+                                           "true" : "false"));
+                       }
                        pvr2_trace(
                                PVR2_TRACE_ERROR_LEGS,
                                "Giving up on command."
@@ -480,10 +489,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
        /* unmask some interrupts */
        pvr2_write_register(hdw, 0x0048, 0xbfffffff);
 
-       /* change some GPIO data */
-       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
-       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
-
        pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
                          hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
 
@@ -526,12 +531,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
                break;
        }
 
-       /* change some GPIO data */
-       /* Note: Bit d7 of dir appears to control the LED.  So we shut it
-          off here. */
-       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
-       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
-
        return status;
 }
 
index ffbc6d09610880535fc04120f3461bc78b112308..abaada31e66ebe06c26bb9ba34a2df0006c58ab2 100644 (file)
 #ifndef _PVRUSB2_FX2_CMD_H_
 #define _PVRUSB2_FX2_CMD_H_
 
-#define FX2CMD_MEM_WRITE_DWORD  0x01
-#define FX2CMD_MEM_READ_DWORD   0x02
+#define FX2CMD_MEM_WRITE_DWORD  0x01u
+#define FX2CMD_MEM_READ_DWORD   0x02u
 
-#define FX2CMD_MEM_READ_64BYTES 0x28
+#define FX2CMD_MEM_READ_64BYTES 0x28u
 
-#define FX2CMD_REG_WRITE        0x04
-#define FX2CMD_REG_READ         0x05
-#define FX2CMD_MEMSEL           0x06
+#define FX2CMD_REG_WRITE        0x04u
+#define FX2CMD_REG_READ         0x05u
+#define FX2CMD_MEMSEL           0x06u
 
-#define FX2CMD_I2C_WRITE        0x08
-#define FX2CMD_I2C_READ         0x09
+#define FX2CMD_I2C_WRITE        0x08u
+#define FX2CMD_I2C_READ         0x09u
 
-#define FX2CMD_GET_USB_SPEED    0x0b
+#define FX2CMD_GET_USB_SPEED    0x0bu
 
-#define FX2CMD_STREAMING_ON     0x36
-#define FX2CMD_STREAMING_OFF    0x37
+#define FX2CMD_STREAMING_ON     0x36u
+#define FX2CMD_STREAMING_OFF    0x37u
 
-#define FX2CMD_FWPOST1          0x52
+#define FX2CMD_FWPOST1          0x52u
 
-#define FX2CMD_POWER_OFF        0xdc
-#define FX2CMD_POWER_ON         0xde
+#define FX2CMD_POWER_OFF        0xdcu
+#define FX2CMD_POWER_ON         0xdeu
 
-#define FX2CMD_DEEP_RESET       0xdd
+#define FX2CMD_DEEP_RESET       0xddu
 
-#define FX2CMD_GET_EEPROM_ADDR  0xeb
-#define FX2CMD_GET_IR_CODE      0xec
+#define FX2CMD_GET_EEPROM_ADDR  0xebu
+#define FX2CMD_GET_IR_CODE      0xecu
+
+#define FX2CMD_HCW_DEMOD_RESETIN       0xf0u
+#define FX2CMD_HCW_DTV_STREAMING_ON    0xf1u
+#define FX2CMD_HCW_DTV_STREAMING_OFF   0xf2u
+
+#define FX2CMD_ONAIR_DTV_STREAMING_ON  0xa0u
+#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
+#define FX2CMD_ONAIR_DTV_POWER_ON      0xa2u
+#define FX2CMD_ONAIR_DTV_POWER_OFF     0xa3u
 
 #endif /* _PVRUSB2_FX2_CMD_H_ */
 
index d7a216b41b7235b14bcd364ef82dc3c946a2b97b..a3fe251d6fd912eeaefc9f07157b702074d67abd 100644 (file)
@@ -163,6 +163,11 @@ struct pvr2_decoder_ctrl {
 #define FW1_STATE_RELOAD 3
 #define FW1_STATE_OK 4
 
+/* What state the device is in if it is a hybrid */
+#define PVR2_PATHWAY_UNKNOWN 0
+#define PVR2_PATHWAY_ANALOG 1
+#define PVR2_PATHWAY_DIGITAL 2
+
 typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
 #define PVR2_I2C_FUNC_CNT 128
 
@@ -182,7 +187,6 @@ struct pvr2_hdw {
        struct workqueue_struct *workqueue;
        struct work_struct workpoll;     /* Update driver state */
        struct work_struct worki2csync;  /* Update i2c clients */
-       struct work_struct workinit;     /* Driver initialization sequence */
 
        /* Video spigot */
        struct pvr2_stream *vid_stream;
@@ -229,17 +233,19 @@ struct pvr2_hdw {
 
        /* Bits of state that describe what is going on with various parts
           of the driver. */
+       int state_pathway_ok;         /* Pathway config is ok */
        int state_encoder_ok;         /* Encoder is operational */
        int state_encoder_run;        /* Encoder is running */
        int state_encoder_config;     /* Encoder is configured */
        int state_encoder_waitok;     /* Encoder pre-wait done */
+       int state_encoder_runok;      /* Encoder has run for >= .25 sec */
        int state_decoder_run;        /* Decoder is running */
        int state_usbstream_run;      /* FX2 is streaming */
        int state_decoder_quiescent;  /* Decoder idle for > 50msec */
        int state_pipeline_config;    /* Pipeline is configured */
-       int state_pipeline_req;                /* Somebody wants to stream */
-       int state_pipeline_pause;              /* Pipeline must be paused */
-       int state_pipeline_idle;               /* Pipeline not running */
+       int state_pipeline_req;       /* Somebody wants to stream */
+       int state_pipeline_pause;     /* Pipeline must be paused */
+       int state_pipeline_idle;      /* Pipeline not running */
 
        /* This is the master state of the driver.  It is the combined
           result of other bits of state.  Examining this will indicate the
@@ -247,6 +253,9 @@ struct pvr2_hdw {
           PVR2_STATE_xxxx */
        unsigned int master_state;
 
+       /* True if device led is currently on */
+       int led_on;
+
        /* True if states must be re-evaluated */
        int state_stale;
 
@@ -259,6 +268,9 @@ struct pvr2_hdw {
        /* Timer for measuring encoder pre-wait time */
        struct timer_list encoder_wait_timer;
 
+       /* Timer for measuring encoder minimum run time */
+       struct timer_list encoder_run_timer;
+
        /* Place to block while waiting for state changes */
        wait_queue_head_t state_wait_data;
 
@@ -267,6 +279,7 @@ struct pvr2_hdw {
        int flag_disconnected;  /* flag_ok == 0 due to disconnect */
        int flag_init_ok;       /* true if structure is fully initialized */
        int fw1_state;          /* current situation with fw1 */
+       int pathway_state;      /* one of PVR2_PATHWAY_xxx */
        int flag_decoder_missed;/* We've noticed missing decoder */
        int flag_tripped;       /* Indicates overall failure to start */
 
@@ -323,6 +336,11 @@ struct pvr2_hdw {
        int v4l_minor_number_vbi;
        int v4l_minor_number_radio;
 
+       /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
+       unsigned int input_avail_mask;
+       /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
+       unsigned int input_allowed_mask;
+
        /* Location of eeprom or a negative number if none */
        int eeprom_addr;
 
index 2404053a4d8585b5eda3f4822d9ad816e3c3f90a..0a868888f389d2e74004051558511b90a8dd2b88 100644 (file)
 static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
 static DEFINE_MUTEX(pvr2_unit_mtx);
 
-static int ctlchg = 0;
+static int ctlchg;
 static int initusbreset = 1;
-static int procreload = 0;
+static int procreload;
 static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
 static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
 static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
-static int init_pause_msec = 0;
+static int init_pause_msec;
 
 module_param(ctlchg, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
@@ -182,6 +182,7 @@ static const char *control_values_srate[] = {
 
 static const char *control_values_input[] = {
        [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
+       [PVR2_CVAL_INPUT_DTV]       = "dtv",
        [PVR2_CVAL_INPUT_RADIO]     = "radio",
        [PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
        [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
@@ -215,12 +216,45 @@ static const char *pvr2_state_names[] = {
 };
 
 
+struct pvr2_fx2cmd_descdef {
+       unsigned char id;
+       unsigned char *desc;
+};
+
+static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
+       {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
+       {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
+       {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
+       {FX2CMD_REG_WRITE, "write encoder register"},
+       {FX2CMD_REG_READ, "read encoder register"},
+       {FX2CMD_MEMSEL, "encoder memsel"},
+       {FX2CMD_I2C_WRITE, "i2c write"},
+       {FX2CMD_I2C_READ, "i2c read"},
+       {FX2CMD_GET_USB_SPEED, "get USB speed"},
+       {FX2CMD_STREAMING_ON, "stream on"},
+       {FX2CMD_STREAMING_OFF, "stream off"},
+       {FX2CMD_FWPOST1, "fwpost1"},
+       {FX2CMD_POWER_OFF, "power off"},
+       {FX2CMD_POWER_ON, "power on"},
+       {FX2CMD_DEEP_RESET, "deep reset"},
+       {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
+       {FX2CMD_GET_IR_CODE, "get IR code"},
+       {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
+       {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
+       {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
+       {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
+       {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
+       {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
+       {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
+};
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
 static void pvr2_hdw_state_sched(struct pvr2_hdw *);
 static int pvr2_hdw_state_eval(struct pvr2_hdw *);
 static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
 static void pvr2_hdw_worker_i2c(struct work_struct *work);
 static void pvr2_hdw_worker_poll(struct work_struct *work);
-static void pvr2_hdw_worker_init(struct work_struct *work);
 static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
 static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
 static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
@@ -231,6 +265,8 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
 static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
 static void pvr2_hdw_quiescent_timeout(unsigned long);
 static void pvr2_hdw_encoder_wait_timeout(unsigned long);
+static void pvr2_hdw_encoder_run_timeout(unsigned long);
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
 static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
                                unsigned int timeout,int probe_fl,
                                void *write_data,unsigned int write_len,
@@ -367,26 +403,14 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
        return 0;
 }
 
-static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
 {
-       struct pvr2_hdw *hdw = cptr->hdw;
-
-       if (hdw->input_val != v) {
-               hdw->input_val = v;
-               hdw->input_dirty = !0;
-       }
+       return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
+}
 
-       /* Handle side effects - if we switch to a mode that needs the RF
-          tuner, then select the right frequency choice as well and mark
-          it dirty. */
-       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               hdw->freqSelector = 0;
-               hdw->freqDirty = !0;
-       } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
-               hdw->freqSelector = 1;
-               hdw->freqDirty = !0;
-       }
-       return 0;
+static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+{
+       return pvr2_hdw_set_input(cptr->hdw,v);
 }
 
 static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
@@ -803,6 +827,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "input",
                .internal_id = PVR2_CID_INPUT,
                .default_value = PVR2_CVAL_INPUT_TV,
+               .check_value = ctrl_check_input,
                DEFREF(input),
                DEFENUM(control_values_input),
        },{
@@ -982,7 +1007,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
 
 /* Set the currently tuned frequency and account for all possible
    driver-core side effects of this action. */
-void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
 {
        if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
                if (hdw->freqSelector) {
@@ -1195,6 +1220,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
           time we configure the encoder, then we'll fully configure it. */
        hdw->enc_cur_valid = 0;
 
+       /* Encoder is about to be reset so note that as far as we're
+          concerned now, the encoder has never been run. */
+       del_timer_sync(&hdw->encoder_run_timer);
+       if (hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = 0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+       }
+
        /* First prepare firmware loading */
        ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
        ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
@@ -1212,19 +1245,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
        ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
-               hdw->cmd_buffer[1] = 0;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload prep failed, ret=%d",ret);
                release_firmware(fw_entry);
-               return ret;
+               goto done;
        }
 
        /* Now send firmware */
@@ -1237,7 +1265,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                           " must be a multiple of %zu bytes",
                           fw_files[fwidx],sizeof(u32));
                release_firmware(fw_entry);
-               return -1;
+               ret = -EINVAL;
+               goto done;
        }
 
        fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
@@ -1245,7 +1274,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                release_firmware(fw_entry);
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "failed to allocate memory for firmware2 upload");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto done;
        }
 
        pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
@@ -1276,23 +1306,27 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload transfer failure");
-               return ret;
+               goto done;
        }
 
        /* Finish upload */
 
        ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
        ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
-               hdw->cmd_buffer[1] = 0;
-               ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "firmware2 upload post-proc failure");
        }
+
+ done:
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
        return ret;
 }
 
@@ -1364,11 +1398,6 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
 }
 
 
-const char *pvr2_hdw_get_state_name(unsigned int id)
-{
-       if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL;
-       return pvr2_state_names[id];
-}
 
 
 int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
@@ -1495,7 +1524,7 @@ struct pvr2_std_hack {
    default - which can always be overridden explicitly - and if the user
    has otherwise named a default then that default will always be used in
    place of this table. */
-const static struct pvr2_std_hack std_eeprom_maps[] = {
+static const struct pvr2_std_hack std_eeprom_maps[] = {
        {       /* PAL(B/G) */
                .pat = V4L2_STD_B|V4L2_STD_GH,
                .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
@@ -1712,6 +1741,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
 
        if (!pvr2_hdw_dev_ok(hdw)) return;
 
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
+
        pvr2_hdw_commit_setup(hdw);
 
        hdw->vid_stream = pvr2_stream_create();
@@ -1805,12 +1841,37 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
 }
 
 
-/* Create and return a structure for interacting with the underlying
-   hardware */
+/* Perform second stage initialization.  Set callback pointer first so that
+   we can avoid a possible initialization race (if the kernel thread runs
+   before the callback has been set). */
+int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
+                       void (*callback_func)(void *),
+                       void *callback_data)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->flag_disconnected) {
+                       /* Handle a race here: If we're already
+                          disconnected by this point, then give up.  If we
+                          get past this then we'll remain connected for
+                          the duration of initialization since the entire
+                          initialization sequence is now protected by the
+                          big_lock. */
+                       break;
+               }
+               hdw->state_data = callback_data;
+               hdw->state_func = callback_func;
+               pvr2_hdw_setup(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return hdw->flag_init_ok;
+}
+
+
+/* Create, set up, and return a structure for interacting with the
+   underlying hardware.  */
 struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                 const struct usb_device_id *devid)
 {
-       unsigned int idx,cnt1,cnt2;
+       unsigned int idx,cnt1,cnt2,m;
        struct pvr2_hdw *hdw;
        int valid_std_mask;
        struct pvr2_ctrl *cptr;
@@ -1834,6 +1895,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->encoder_wait_timer.data = (unsigned long)hdw;
        hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
 
+       init_timer(&hdw->encoder_run_timer);
+       hdw->encoder_run_timer.data = (unsigned long)hdw;
+       hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
+
        hdw->master_state = PVR2_STATE_DEAD;
 
        init_waitqueue_head(&hdw->state_wait_data);
@@ -1841,6 +1906,26 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->tuner_signal_stale = !0;
        cx2341x_fill_defaults(&hdw->enc_ctl_state);
 
+       /* Calculate which inputs are OK */
+       m = 0;
+       if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
+       if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
+               m |= 1 << PVR2_CVAL_INPUT_DTV;
+       }
+       if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
+       if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
+       if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
+       hdw->input_avail_mask = m;
+       hdw->input_allowed_mask = hdw->input_avail_mask;
+
+       /* If not a hybrid device, pathway_state never changes.  So
+          initialize it here to what it should forever be. */
+       if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
+               hdw->pathway_state = PVR2_PATHWAY_ANALOG;
+       } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
+               hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
+       }
+
        hdw->control_cnt = CTRLDEF_COUNT;
        hdw->control_cnt += MPEGDEF_COUNT;
        hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
@@ -1858,6 +1943,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                cptr = hdw->controls + idx;
                cptr->info = control_defs+idx;
        }
+
+       /* Ensure that default input choice is a valid one. */
+       m = hdw->input_avail_mask;
+       if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+               if (!((1 << idx) & m)) continue;
+               hdw->input_val = idx;
+               break;
+       }
+
        /* Define and configure additional controls from cx2341x module. */
        hdw->mpeg_ctrl_info = kzalloc(
                sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
@@ -1981,7 +2075,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        hdw->workqueue = create_singlethread_workqueue(hdw->name);
        INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
        INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
-       INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init);
 
        pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
                   hdw->unit_number,hdw->name);
@@ -2003,11 +2096,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
        mutex_init(&hdw->ctl_lock_mutex);
        mutex_init(&hdw->big_lock_mutex);
 
-       queue_work(hdw->workqueue,&hdw->workinit);
        return hdw;
  fail:
        if (hdw) {
                del_timer_sync(&hdw->quiescent_timer);
+               del_timer_sync(&hdw->encoder_run_timer);
                del_timer_sync(&hdw->encoder_wait_timer);
                if (hdw->workqueue) {
                        flush_workqueue(hdw->workqueue);
@@ -2064,13 +2157,14 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
 {
        if (!hdw) return;
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
-       del_timer_sync(&hdw->quiescent_timer);
-       del_timer_sync(&hdw->encoder_wait_timer);
        if (hdw->workqueue) {
                flush_workqueue(hdw->workqueue);
                destroy_workqueue(hdw->workqueue);
                hdw->workqueue = NULL;
        }
+       del_timer_sync(&hdw->quiescent_timer);
+       del_timer_sync(&hdw->encoder_run_timer);
+       del_timer_sync(&hdw->encoder_wait_timer);
        if (hdw->fw_buffer) {
                kfree(hdw->fw_buffer);
                hdw->fw_buffer = NULL;
@@ -2352,6 +2446,18 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                }
        }
 
+       if (hdw->input_dirty && hdw->state_pathway_ok &&
+           (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
+             PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
+            hdw->pathway_state)) {
+               /* Change of mode being asked for... */
+               hdw->state_pathway_ok = 0;
+               trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Can't commit anything until pathway is ok. */
+               return 0;
+       }
        /* If any of the below has changed, then we can't do the update
           while the pipeline is running.  Pipeline must be paused first
           and decoder -> encoder connection be made quiescent before we
@@ -2405,12 +2511,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                hdw->active_stream_type = hdw->desired_stream_type;
        }
 
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               u32 b;
+               /* Handle GOTVIEW audio switching */
+               pvr2_hdw_gpio_get_out(hdw,&b);
+               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+                       /* Set GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
+               } else {
+                       /* Clear GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
+               }
+       }
+
        /* Now execute i2c core update */
        pvr2_i2c_core_sync(hdw);
 
-       if (hdw->state_encoder_run) {
-               /* If encoder isn't running, then this will get worked out
-                  later when we start the encoder. */
+       if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
+           hdw->state_encoder_run) {
+               /* If encoder isn't running or it can't be touched, then
+                  this will get worked out later when we start the
+                  encoder. */
                if (pvr2_encoder_adjust(hdw) < 0) return !0;
        }
 
@@ -2453,15 +2575,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work)
 }
 
 
-static void pvr2_hdw_worker_init(struct work_struct *work)
-{
-       struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit);
-       LOCK_TAKE(hdw->big_lock); do {
-               pvr2_hdw_setup(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
 static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
 {
        return wait_event_interruptible(
@@ -2471,17 +2584,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
 }
 
 
-void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw,
-                                void (*callback_func)(void *),
-                                void *callback_data)
-{
-       LOCK_TAKE(hdw->big_lock); do {
-               hdw->state_data = callback_data;
-               hdw->state_func = callback_func;
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
 {
@@ -3050,6 +3152,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
                                    read_data,read_len);
 }
 
+
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
+{
+       int ret;
+       unsigned int cnt = 1;
+       unsigned int args = 0;
+       LOCK_TAKE(hdw->ctl_lock);
+       hdw->cmd_buffer[0] = cmdcode & 0xffu;
+       args = (cmdcode >> 8) & 0xffu;
+       args = (args > 2) ? 2 : args;
+       if (args) {
+               cnt += args;
+               hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
+               if (args > 1) {
+                       hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
+               }
+       }
+       if (pvrusb2_debug & PVR2_TRACE_INIT) {
+               unsigned int idx;
+               unsigned int ccnt,bcnt;
+               char tbuf[50];
+               cmdcode &= 0xffu;
+               bcnt = 0;
+               ccnt = scnprintf(tbuf+bcnt,
+                                sizeof(tbuf)-bcnt,
+                                "Sending FX2 command 0x%x",cmdcode);
+               bcnt += ccnt;
+               for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
+                       if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                " \"%s\"",
+                                                pvr2_fx2cmd_desc[idx].desc);
+                               bcnt += ccnt;
+                               break;
+                       }
+               }
+               if (args) {
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        " (%u",hdw->cmd_buffer[1]);
+                       bcnt += ccnt;
+                       if (args > 1) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                ",%u",hdw->cmd_buffer[2]);
+                               bcnt += ccnt;
+                       }
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        ")");
+                       bcnt += ccnt;
+               }
+               pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
+       }
+       ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
+       LOCK_GIVE(hdw->ctl_lock);
+       return ret;
+}
+
+
 int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
 {
        int ret;
@@ -3157,25 +3320,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
 
 int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
-               hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
 }
 
 
 int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
-               hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
+}
+
+
+int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
+{
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
 }
 
 
@@ -3200,16 +3357,173 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
 }
 
 
+static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,
+                                    FX2CMD_HCW_DEMOD_RESETIN |
+                                    (1 << 8) |
+                                    ((onoff ? 1 : 0) << 16));
+}
+
+
+static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_POWER_ON :
+                                         FX2CMD_ONAIR_DTV_POWER_OFF));
+}
+
+
+static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
+                                               int onoff)
+{
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_STREAMING_ON :
+                                         FX2CMD_ONAIR_DTV_STREAMING_OFF));
+}
+
+
+static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
+{
+       int cmode;
+       /* Compare digital/analog desired setting with current setting.  If
+          they don't match, fix it... */
+       cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
+       if (cmode == hdw->pathway_state) {
+               /* They match; nothing to do */
+               return;
+       }
+
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
+               if (cmode == PVR2_PATHWAY_ANALOG) {
+                       /* If moving to analog mode, also force the decoder
+                          to reset.  If no decoder is attached, then it's
+                          ok to ignore this because if/when the decoder
+                          attaches, it will reset itself at that time. */
+                       pvr2_hdw_cmd_decoder_reset(hdw);
+               }
+               break;
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               /* Supposedly we should always have the power on whether in
+                  digital or analog mode.  But for now do what appears to
+                  work... */
+               pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
+               break;
+       default: break;
+       }
+
+       pvr2_hdw_untrip_unlocked(hdw);
+       hdw->pathway_state = cmode;
+}
+
+
+void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
+{
+       /* change some GPIO data
+        *
+        * note: bit d7 of dir appears to control the LED,
+        * so we shut it off here.
+        *
+        */
+       if (onoff) {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
+       } else {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
+       }
+       pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
+}
+
+
+typedef void (*led_method_func)(struct pvr2_hdw *,int);
+
+static led_method_func led_methods[] = {
+       [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
+};
+
+
+/* Toggle LED */
+static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
+{
+       unsigned int scheme_id;
+       led_method_func fp;
+
+       if ((!onoff) == (!hdw->led_on)) return;
+
+       hdw->led_on = onoff != 0;
+
+       scheme_id = hdw->hdw_desc->led_scheme;
+       if (scheme_id < ARRAY_SIZE(led_methods)) {
+               fp = led_methods[scheme_id];
+       } else {
+               fp = NULL;
+       }
+
+       if (fp) (*fp)(hdw,onoff);
+}
+
+
 /* Stop / start video stream transport */
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
 {
-       int status;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] =
-                       (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
-               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-       return status;
+       int ret;
+
+       /* If we're in analog mode, then just issue the usual analog
+          command. */
+       if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_STREAMING_ON :
+                                             FX2CMD_STREAMING_OFF));
+               /*Note: Not reached */
+       }
+
+       if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
+               /* Whoops, we don't know what mode we're in... */
+               return -EINVAL;
+       }
+
+       /* To get here we have to be in digital mode.  The mechanism here
+          is unfortunately different for different vendors.  So we switch
+          on the device's digital scheme attribute in order to figure out
+          what to do. */
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_HCW_DTV_STREAMING_ON :
+                                             FX2CMD_HCW_DTV_STREAMING_OFF));
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               ret = pvr2_issue_simple_cmd(hdw,
+                                           (runFl ?
+                                            FX2CMD_STREAMING_ON :
+                                            FX2CMD_STREAMING_OFF));
+               if (ret) return ret;
+               return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
+       default:
+               return -EINVAL;
+       }
+}
+
+
+/* Evaluate whether or not state_pathway_ok can change */
+static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_pathway_ok) {
+               /* Nothing to do if pathway is already ok */
+               return 0;
+       }
+       if (!hdw->state_pipeline_idle) {
+               /* Not allowed to change anything if pipeline is not idle */
+               return 0;
+       }
+       pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
+       hdw->state_pathway_ok = !0;
+       trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
+       return !0;
 }
 
 
@@ -3222,6 +3536,12 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
        if (hdw->state_encoder_config) return 0;
        if (hdw->state_decoder_run) return 0;
        if (hdw->state_usbstream_run) return 0;
+       if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
+               if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
+       } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
+               return 0;
+       }
+
        if (pvr2_upload_firmware2(hdw) < 0) {
                hdw->flag_tripped = !0;
                trace_stbit("flag_tripped",hdw->flag_tripped);
@@ -3247,7 +3567,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
                /* paranoia - solve race if timer just completed */
                del_timer_sync(&hdw->encoder_wait_timer);
        } else {
-               if (!hdw->state_encoder_ok ||
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_encoder_ok ||
                    !hdw->state_pipeline_idle ||
                    hdw->state_pipeline_pause ||
                    !hdw->state_pipeline_req ||
@@ -3296,20 +3618,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
 }
 
 
+/* Return true if the encoder should not be running. */
+static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Encoder isn't healthy at the moment, so stop it. */
+               return !0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Mode is not understood at the moment (i.e. it wants to
+                  change), so encoder must be stopped. */
+               return !0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (!hdw->state_decoder_run) {
+                       /* We're in analog mode and the decoder is not
+                          running; thus the encoder should be stopped as
+                          well. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if (hdw->state_encoder_runok) {
+                       /* This is a funny case.  We're in digital mode so
+                          really the encoder should be stopped.  However
+                          if it really is running, only kill it after
+                          runok has been set.  This gives a chance for the
+                          onair quirk to function (encoder must run
+                          briefly first, at least once, before onair
+                          digital streaming can work). */
+                       return !0;
+               }
+               break;
+       default:
+               /* Unknown mode; so encoder should be stopped. */
+               return !0;
+       }
+
+       /* If we get here, we haven't found a reason to stop the
+          encoder. */
+       return 0;
+}
+
+
+/* Return true if the encoder should be running. */
+static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Don't run the encoder if it isn't healthy... */
+               return 0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Don't run the encoder if we don't (yet) know what mode
+                  we need to be in... */
+               return 0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (hdw->state_decoder_run) {
+                       /* In analog mode, if the decoder is running, then
+                          run the encoder. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if ((hdw->hdw_desc->digital_control_scheme ==
+                    PVR2_DIGITAL_SCHEME_ONAIR) &&
+                   !hdw->state_encoder_runok) {
+                       /* This is a quirk.  OnAir hardware won't stream
+                          digital until the encoder has been run at least
+                          once, for a minimal period of time (empiricially
+                          measured to be 1/4 second).  So if we're on
+                          OnAir hardware and the encoder has never been
+                          run at all, then start the encoder.  Normal
+                          state machine logic in the driver will
+                          automatically handle the remaining bits. */
+                       return !0;
+               }
+               break;
+       default:
+               /* For completeness (unknown mode; encoder won't run ever) */
+               break;
+       }
+       /* If we get here, then we haven't found any reason to run the
+          encoder, so don't run it. */
+       return 0;
+}
+
+
 /* Evaluate whether or not state_encoder_run can change */
 static int state_eval_encoder_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_encoder_run) {
+               if (!state_check_disable_encoder_run(hdw)) return 0;
                if (hdw->state_encoder_ok) {
-                       if (hdw->state_decoder_run) return 0;
+                       del_timer_sync(&hdw->encoder_run_timer);
                        if (pvr2_encoder_stop(hdw) < 0) return !0;
                }
                hdw->state_encoder_run = 0;
        } else {
-               if (!hdw->state_encoder_ok) return 0;
-               if (!hdw->state_decoder_run) return 0;
+               if (!state_check_enable_encoder_run(hdw)) return 0;
                if (pvr2_encoder_start(hdw) < 0) return !0;
                hdw->state_encoder_run = !0;
+               if (!hdw->state_encoder_runok) {
+                       hdw->encoder_run_timer.expires =
+                               jiffies + (HZ*250/1000);
+                       add_timer(&hdw->encoder_run_timer);
+               }
        }
        trace_stbit("state_encoder_run",hdw->state_encoder_run);
        return !0;
@@ -3338,13 +3756,27 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
 }
 
 
+/* Timeout function for encoder run timer. */
+static void pvr2_hdw_encoder_run_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       if (!hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = !0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+               hdw->state_stale = !0;
+               queue_work(hdw->workqueue,&hdw->workpoll);
+       }
+}
+
+
 /* Evaluate whether or not state_decoder_run can change */
 static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_decoder_run) {
                if (hdw->state_encoder_ok) {
                        if (hdw->state_pipeline_req &&
-                           !hdw->state_pipeline_pause) return 0;
+                           !hdw->state_pipeline_pause &&
+                           hdw->state_pathway_ok) return 0;
                }
                if (!hdw->flag_decoder_missed) {
                        pvr2_decoder_enable(hdw,0);
@@ -3377,7 +3809,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
                           hopefully further stabilize the encoder. */
                        return 0;
                }
-               if (!hdw->state_pipeline_req ||
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_pipeline_req ||
                    hdw->state_pipeline_pause ||
                    !hdw->state_pipeline_config ||
                    !hdw->state_encoder_config ||
@@ -3398,16 +3832,43 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
 static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
 {
        if (hdw->state_usbstream_run) {
-               if (hdw->state_encoder_ok) {
-                       if (hdw->state_encoder_run) return 0;
+               int fl = !0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       fl = (hdw->state_encoder_ok &&
+                             hdw->state_encoder_run);
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       fl = hdw->state_encoder_ok;
+               }
+               if (fl &&
+                   hdw->state_pipeline_req &&
+                   !hdw->state_pipeline_pause &&
+                   hdw->state_pathway_ok) {
+                       return 0;
                }
                pvr2_hdw_cmd_usbstream(hdw,0);
                hdw->state_usbstream_run = 0;
        } else {
-               if (!hdw->state_encoder_ok ||
-                   !hdw->state_encoder_run ||
-                   !hdw->state_pipeline_req ||
-                   hdw->state_pipeline_pause) return 0;
+               if (!hdw->state_pipeline_req ||
+                   hdw->state_pipeline_pause ||
+                   !hdw->state_pathway_ok) return 0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       if (!hdw->state_encoder_ok ||
+                           !hdw->state_encoder_run) return 0;
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       if (!hdw->state_encoder_ok) return 0;
+                       if (hdw->state_encoder_run) return 0;
+                       if (hdw->hdw_desc->digital_control_scheme ==
+                           PVR2_DIGITAL_SCHEME_ONAIR) {
+                               /* OnAir digital receivers won't stream
+                                  unless the analog encoder has run first.
+                                  Why?  I have no idea.  But don't even
+                                  try until we know the analog side is
+                                  known to have run. */
+                               if (!hdw->state_encoder_runok) return 0;
+                       }
+               }
                if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
                hdw->state_usbstream_run = !0;
        }
@@ -3453,7 +3914,8 @@ static int state_update_pipeline_state(struct pvr2_hdw *hdw)
 typedef int (*state_eval_func)(struct pvr2_hdw *);
 
 /* Set of functions to be run to evaluate various states in the driver. */
-const static state_eval_func eval_funcs[] = {
+static const state_eval_func eval_funcs[] = {
+       state_eval_pathway_ok,
        state_eval_pipeline_config,
        state_eval_encoder_ok,
        state_eval_encoder_config,
@@ -3501,6 +3963,34 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
 }
 
 
+static unsigned int print_input_mask(unsigned int msk,
+                                    char *buf,unsigned int acnt)
+{
+       unsigned int idx,ccnt;
+       unsigned int tcnt = 0;
+       for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
+               if (!((1 << idx) & msk)) continue;
+               ccnt = scnprintf(buf+tcnt,
+                                acnt-tcnt,
+                                "%s%s",
+                                (tcnt ? ", " : ""),
+                                control_values_input[idx]);
+               tcnt += ccnt;
+       }
+       return tcnt;
+}
+
+
+static const char *pvr2_pathway_state_name(int id)
+{
+       switch (id) {
+       case PVR2_PATHWAY_ANALOG: return "analog";
+       case PVR2_PATHWAY_DIGITAL: return "digital";
+       default: return "unknown";
+       }
+}
+
+
 static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
                                             char *buf,unsigned int acnt)
 {
@@ -3508,13 +3998,15 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
        case 0:
                return scnprintf(
                        buf,acnt,
-                       "driver:%s%s%s%s%s",
+                       "driver:%s%s%s%s%s <mode=%s>",
                        (hdw->flag_ok ? " <ok>" : " <fail>"),
                        (hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
                        (hdw->flag_disconnected ? " <disconnected>" :
                         " <connected>"),
                        (hdw->flag_tripped ? " <tripped>" : ""),
-                       (hdw->flag_decoder_missed ? " <no decoder>" : ""));
+                       (hdw->flag_decoder_missed ? " <no decoder>" : ""),
+                       pvr2_pathway_state_name(hdw->pathway_state));
+
        case 1:
                return scnprintf(
                        buf,acnt,
@@ -3527,7 +4019,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
        case 2:
                return scnprintf(
                        buf,acnt,
-                       "worker:%s%s%s%s%s%s",
+                       "worker:%s%s%s%s%s%s%s",
                        (hdw->state_decoder_run ?
                         " <decode:run>" :
                         (hdw->state_decoder_quiescent ?
@@ -3537,20 +4029,65 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
                        (hdw->state_encoder_ok ?
                         "" : " <encode:init>"),
                        (hdw->state_encoder_run ?
-                        " <encode:run>" : " <encode:stop>"),
+                        (hdw->state_encoder_runok ?
+                         " <encode:run>" :
+                         " <encode:firstrun>") :
+                        (hdw->state_encoder_runok ?
+                         " <encode:stop>" :
+                         " <encode:virgin>")),
                        (hdw->state_encoder_config ?
                         " <encode:configok>" :
                         (hdw->state_encoder_waitok ?
-                         "" : " <encode:wait>")),
+                         "" : " <encode:waitok>")),
                        (hdw->state_usbstream_run ?
-                        " <usb:run>" : " <usb:stop>"));
-               break;
+                        " <usb:run>" : " <usb:stop>"),
+                       (hdw->state_pathway_ok ?
+                        " <pathway:ok>" : ""));
        case 3:
                return scnprintf(
                        buf,acnt,
                        "state: %s",
                        pvr2_get_state_name(hdw->master_state));
-               break;
+       case 4: {
+               unsigned int tcnt = 0;
+               unsigned int ccnt;
+
+               ccnt = scnprintf(buf,
+                                acnt,
+                                "Hardware supported inputs: ");
+               tcnt += ccnt;
+               tcnt += print_input_mask(hdw->input_avail_mask,
+                                        buf+tcnt,
+                                        acnt-tcnt);
+               if (hdw->input_avail_mask != hdw->input_allowed_mask) {
+                       ccnt = scnprintf(buf+tcnt,
+                                        acnt-tcnt,
+                                        "; allowed inputs: ");
+                       tcnt += ccnt;
+                       tcnt += print_input_mask(hdw->input_allowed_mask,
+                                                buf+tcnt,
+                                                acnt-tcnt);
+               }
+               return tcnt;
+       }
+       case 5: {
+               struct pvr2_stream_stats stats;
+               if (!hdw->vid_stream) break;
+               pvr2_stream_get_stats(hdw->vid_stream,
+                                     &stats,
+                                     0);
+               return scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+       }
        default: break;
        }
        return 0;
@@ -3596,6 +4133,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
        unsigned int st;
        int state_updated = 0;
        int callback_flag = 0;
+       int analog_mode;
 
        pvr2_trace(PVR2_TRACE_STBITS,
                   "Drive state check START");
@@ -3606,18 +4144,23 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
        /* Process all state and get back over disposition */
        state_updated = pvr2_hdw_state_update(hdw);
 
+       analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
+
        /* Update master state based upon all other states. */
        if (!hdw->flag_ok) {
                st = PVR2_STATE_DEAD;
        } else if (hdw->fw1_state != FW1_STATE_OK) {
                st = PVR2_STATE_COLD;
-       } else if (!hdw->state_encoder_ok) {
+       } else if ((analog_mode ||
+                   hdw->hdw_desc->flag_digital_requires_cx23416) &&
+                  !hdw->state_encoder_ok) {
                st = PVR2_STATE_WARM;
-       } else if (hdw->flag_tripped || hdw->flag_decoder_missed) {
+       } else if (hdw->flag_tripped ||
+                  (analog_mode && hdw->flag_decoder_missed)) {
                st = PVR2_STATE_ERROR;
-       } else if (hdw->state_encoder_run &&
-                  hdw->state_decoder_run &&
-                  hdw->state_usbstream_run) {
+       } else if (hdw->state_usbstream_run &&
+                  (!analog_mode ||
+                   (hdw->state_encoder_run && hdw->state_decoder_run))) {
                st = PVR2_STATE_RUN;
        } else {
                st = PVR2_STATE_READY;
@@ -3627,6 +4170,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
                           "Device state change from %s to %s",
                           pvr2_get_state_name(hdw->master_state),
                           pvr2_get_state_name(st));
+               pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
                hdw->master_state = st;
                state_updated = !0;
                callback_flag = !0;
@@ -3656,47 +4200,6 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
 }
 
 
-void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
-                                     struct pvr2_hdw_debug_info *ptr)
-{
-       ptr->big_lock_held = hdw->big_lock_held;
-       ptr->ctl_lock_held = hdw->ctl_lock_held;
-       ptr->flag_disconnected = hdw->flag_disconnected;
-       ptr->flag_init_ok = hdw->flag_init_ok;
-       ptr->flag_ok = hdw->flag_ok;
-       ptr->fw1_state = hdw->fw1_state;
-       ptr->flag_decoder_missed = hdw->flag_decoder_missed;
-       ptr->flag_tripped = hdw->flag_tripped;
-       ptr->state_encoder_ok = hdw->state_encoder_ok;
-       ptr->state_encoder_run = hdw->state_encoder_run;
-       ptr->state_decoder_run = hdw->state_decoder_run;
-       ptr->state_usbstream_run = hdw->state_usbstream_run;
-       ptr->state_decoder_quiescent = hdw->state_decoder_quiescent;
-       ptr->state_pipeline_config = hdw->state_pipeline_config;
-       ptr->state_pipeline_req = hdw->state_pipeline_req;
-       ptr->state_pipeline_pause = hdw->state_pipeline_pause;
-       ptr->state_pipeline_idle = hdw->state_pipeline_idle;
-       ptr->cmd_debug_state = hdw->cmd_debug_state;
-       ptr->cmd_code = hdw->cmd_debug_code;
-       ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
-       ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
-       ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
-       ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
-       ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
-       ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
-       ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
-}
-
-
-void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
-                                   struct pvr2_hdw_debug_info *ptr)
-{
-       LOCK_TAKE(hdw->ctl_lock); do {
-               pvr2_hdw_get_debug_info_unlocked(hdw,ptr);
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-}
-
-
 int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
 {
        return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
@@ -3756,6 +4259,80 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
 }
 
 
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
+{
+       return hdw->input_avail_mask;
+}
+
+
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
+{
+       return hdw->input_allowed_mask;
+}
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
+{
+       if (hdw->input_val != v) {
+               hdw->input_val = v;
+               hdw->input_dirty = !0;
+       }
+
+       /* Handle side effects - if we switch to a mode that needs the RF
+          tuner, then select the right frequency choice as well and mark
+          it dirty. */
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               hdw->freqSelector = 0;
+               hdw->freqDirty = !0;
+       } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
+                  (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
+               hdw->freqSelector = 1;
+               hdw->freqDirty = !0;
+       }
+       return 0;
+}
+
+
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
+                              unsigned int change_mask,
+                              unsigned int change_val)
+{
+       int ret = 0;
+       unsigned int nv,m,idx;
+       LOCK_TAKE(hdw->big_lock);
+       do {
+               nv = hdw->input_allowed_mask & ~change_mask;
+               nv |= (change_val & change_mask);
+               nv &= hdw->input_avail_mask;
+               if (!nv) {
+                       /* No legal modes left; return error instead. */
+                       ret = -EPERM;
+                       break;
+               }
+               hdw->input_allowed_mask = nv;
+               if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
+                       /* Current mode is still in the allowed mask, so
+                          we're done. */
+                       break;
+               }
+               /* Select and switch to a mode that is still in the allowed
+                  mask */
+               if (!hdw->input_allowed_mask) {
+                       /* Nothing legal; give up */
+                       break;
+               }
+               m = hdw->input_allowed_mask;
+               for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+                       if (!((1 << idx) & m)) continue;
+                       pvr2_hdw_set_input(hdw,idx);
+                       break;
+               }
+       } while (0);
+       LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
 /* Find I2C address of eeprom */
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 {
index 3ad7a13d6c391839a3135e117ae1102c20a888b1..20295e0c19954efe6e3784a781aa0c6c445551ac 100644 (file)
 
 /* Legal values for the INPUT state variable */
 #define PVR2_CVAL_INPUT_TV 0
-#define PVR2_CVAL_INPUT_SVIDEO 1
+#define PVR2_CVAL_INPUT_DTV 1
 #define PVR2_CVAL_INPUT_COMPOSITE 2
-#define PVR2_CVAL_INPUT_RADIO 3
+#define PVR2_CVAL_INPUT_SVIDEO 3
+#define PVR2_CVAL_INPUT_RADIO 4
 
 enum pvr2_config {
        pvr2_config_empty,    /* No configuration */
@@ -90,9 +91,6 @@ enum pvr2_v4l_type {
 /* Translate configuration enum to a string label */
 const char *pvr2_config_get_name(enum pvr2_config);
 
-/* Translate a master state enum to a string label */
-const char *pvr2_hdw_get_state_name(unsigned int);
-
 struct pvr2_hdw;
 
 /* Create and return a structure for interacting with the underlying
@@ -100,14 +98,15 @@ struct pvr2_hdw;
 struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                 const struct usb_device_id *devid);
 
+/* Perform second stage initialization, passing in a notification callback
+   for when the master state changes. */
+int pvr2_hdw_initialize(struct pvr2_hdw *,
+                       void (*callback_func)(void *),
+                       void *callback_data);
+
 /* Destroy hardware interaction structure */
 void pvr2_hdw_destroy(struct pvr2_hdw *);
 
-/* Register a function to be called whenever the master state changes. */
-void pvr2_hdw_set_state_callback(struct pvr2_hdw *,
-                                void (*callback_func)(void *),
-                                void *callback_data);
-
 /* Return true if in the ready (normal) state */
 int pvr2_hdw_dev_ok(struct pvr2_hdw *);
 
@@ -146,6 +145,23 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
 /* Commit all control changes made up to this point */
 int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
 
+/* Return a bit mask of valid input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
+
+/* Return a bit mask of allowed input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
+
+/* Change the set of allowed input selections for this device.  Both
+   change_mask and change_valu are mask bits according to
+   PVR_CVAL_INPUT_xxxx definitions.  The change_mask parameter indicate
+   which settings are being changed and the change_val parameter indicates
+   whether corresponding settings are being set or cleared. */
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
+                              unsigned int change_mask,
+                              unsigned int change_val);
+
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
 
@@ -250,6 +266,9 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
 /* Execute simple reset command */
 int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
 
+/* suspend */
+int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *);
+
 /* Order decoder to reset */
 int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
 
index 62867fa3517ae4cd201b2971372aa180ccf716d8..793c89a8d672c513c2ea72fb54732008e9c7dd48 100644 (file)
@@ -35,7 +35,7 @@
 
 */
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
index a9889ff96ecc945b1f344c9fd4ab7e8eced695e0..7aff8b720064c864226ed0502d4ba60365c95f1e 100644 (file)
@@ -80,6 +80,10 @@ struct pvr2_stream {
        /* Tracking state for tolerating errors */
        unsigned int fail_count;
        unsigned int fail_tolerance;
+
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
 };
 
 struct pvr2_buffer {
@@ -446,6 +450,8 @@ static void buffer_complete(struct urb *urb)
            (urb->status == -ENOENT) ||
            (urb->status == -ECONNRESET) ||
            (urb->status == -ESHUTDOWN)) {
+               (sp->buffers_processed)++;
+               sp->bytes_processed += urb->actual_length;
                bp->used_count = urb->actual_length;
                if (sp->fail_count) {
                        pvr2_trace(PVR2_TRACE_TOLERANCE,
@@ -457,11 +463,13 @@ static void buffer_complete(struct urb *urb)
                // We can tolerate this error, because we're below the
                // threshold...
                (sp->fail_count)++;
+               (sp->buffers_failed)++;
                pvr2_trace(PVR2_TRACE_TOLERANCE,
                           "stream %p ignoring error %d"
                           " - fail count increased to %u",
                           sp,urb->status,sp->fail_count);
        } else {
+               (sp->buffers_failed)++;
                bp->status = urb->status;
        }
        spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -515,6 +523,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
        } while(0); mutex_unlock(&sp->mutex);
 }
 
+void pvr2_stream_get_stats(struct pvr2_stream *sp,
+                          struct pvr2_stream_stats *stats,
+                          int zero_counts)
+{
+       unsigned long irq_flags;
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       if (stats) {
+               stats->buffers_in_queue = sp->q_count;
+               stats->buffers_in_idle = sp->i_count;
+               stats->buffers_in_ready = sp->r_count;
+               stats->buffers_processed = sp->buffers_processed;
+               stats->buffers_failed = sp->buffers_failed;
+               stats->bytes_processed = sp->bytes_processed;
+       }
+       if (zero_counts) {
+               sp->buffers_processed = 0;
+               sp->buffers_failed = 0;
+               sp->bytes_processed = 0;
+       }
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
 /* Query / set the nominal buffer count */
 int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
 {
index 93279cc2a35e7e29785b8fd4346b32e5f1d0c2f7..42fcf8281a879c10624157043bb7681bcac29ddc 100644 (file)
@@ -36,6 +36,15 @@ enum pvr2_buffer_state {
 struct pvr2_stream;
 struct pvr2_buffer;
 
+struct pvr2_stream_stats {
+       unsigned int buffers_in_queue;
+       unsigned int buffers_in_idle;
+       unsigned int buffers_in_ready;
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
+};
+
 /* Initialize / tear down stream structure */
 struct pvr2_stream *pvr2_stream_create(void);
 void pvr2_stream_destroy(struct pvr2_stream *);
@@ -45,6 +54,9 @@ void pvr2_stream_setup(struct pvr2_stream *,
 void pvr2_stream_set_callback(struct pvr2_stream *,
                              pvr2_stream_callback func,
                              void *data);
+void pvr2_stream_get_stats(struct pvr2_stream *,
+                          struct pvr2_stream_stats *,
+                          int zero_counts);
 
 /* Query / set the nominal buffer count */
 int pvr2_stream_get_buffer_count(struct pvr2_stream *);
index b63b2265503ac174a335e1ca23c5a560e8d1c31c..332aced8a5a1f04d182c19acbe600f474900ff4c 100644 (file)
@@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
 {
        /* Create association with v4l layer */
        pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* Create association with dvb layer */
+       pvr2_dvb_create(pvr);
+#endif
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        pvr2_sysfs_create(pvr,class_ptr);
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -121,6 +125,12 @@ static int __init pvr_init(void)
 
        pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
 
+       ret = pvr2_context_global_init();
+       if (ret != 0) {
+               pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
+               return ret;
+       }
+
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        class_ptr = pvr2_sysfs_class_create();
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -132,6 +142,8 @@ static int __init pvr_init(void)
        if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
                                pvrusb2_debug,pvrusb2_debug);
 
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
+
        return ret;
 }
 
@@ -144,6 +156,10 @@ static void __exit pvr_exit(void)
 #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
        pvr2_sysfs_class_destroy(class_ptr);
 #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       pvr2_context_global_done();
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
 }
 
 module_init(pvr_init);
index da309288daa4c603fd92b6dbd33e3eca5a6a6508..fdc5a2b49ca8568cf73adb1b3f5fe6d69859a814 100644 (file)
@@ -79,7 +79,7 @@ struct std_name {
 #define TSTD_Nc  (V4L2_STD_PAL_Nc)
 #define TSTD_60  (V4L2_STD_PAL_60)
 
-#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
 
 /* Mapping of standard bits to color system */
 static const struct std_name std_groups[] = {
@@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
        struct v4l2_standard *stddefs;
 
        if (pvrusb2_debug & PVR2_TRACE_STD) {
-               char buf[50];
+               char buf[100];
                bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
                pvr2_trace(
                        PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
@@ -352,8 +352,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
                if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
        }
 
+       /* Don't complain about ATSC standard values */
+       fmsk &= ~CSTD_ATSC;
+
        if (fmsk) {
-               char buf[50];
+               char buf[100];
                bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
                pvr2_trace(
                        PVR2_TRACE_ERROR_LEGS,
index 07f4eae184330a6a91796a3d53e07e24a7c3204a..0ff7a836a8a2493e926ad102664a7814333d026a 100644 (file)
@@ -287,6 +287,8 @@ static ssize_t store_val_norm(int id,struct device *class_dev,
        struct pvr2_sysfs *sfp;
        int ret;
        sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
+                        sfp,id,(int)count,buf);
        ret = store_val_any(id,0,sfp,buf,count);
        if (!ret) ret = count;
        return ret;
@@ -298,6 +300,8 @@ static ssize_t store_val_custom(int id,struct device *class_dev,
        struct pvr2_sysfs *sfp;
        int ret;
        sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
+                        sfp,id,(int)count,buf);
        ret = store_val_any(id,1,sfp,buf,count);
        if (!ret) ret = count;
        return ret;
@@ -604,8 +608,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
 
        ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
        if (ret) {
-               printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "sysfs_create_group error: %d",
+                          ret);
                return;
        }
        cip->created_ok = !0;
@@ -636,15 +641,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
        sfp->debugifc = dip;
        ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                dip->debugcmd_created_ok = !0;
        }
        ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                dip->debuginfo_created_ok = !0;
        }
@@ -847,8 +854,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        class_dev->driver_data = sfp;
        ret = device_register(class_dev);
        if (ret) {
-               printk(KERN_ERR "%s: device_register failed\n",
-                      __FUNCTION__);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_register failed");
                kfree(class_dev);
                return;
        }
@@ -860,8 +867,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_v4l_minor_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->v4l_minor_number_created_ok = !0;
        }
@@ -873,8 +881,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_v4l_radio_minor_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->v4l_radio_minor_number_created_ok = !0;
        }
@@ -885,8 +894,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        sfp->attr_unit_number.store = NULL;
        ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->unit_number_created_ok = !0;
        }
@@ -898,8 +908,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                       &sfp->attr_bus_info);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->bus_info_created_ok = !0;
        }
@@ -911,8 +922,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                 &sfp->attr_hdw_name);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->hdw_name_created_ok = !0;
        }
@@ -924,8 +936,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        ret = device_create_file(sfp->class_dev,
                                 &sfp->attr_hdw_desc);
        if (ret < 0) {
-               printk(KERN_WARNING "%s: device_create_file error: %d\n",
-                      __FUNCTION__, ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
        } else {
                sfp->hdw_desc_created_ok = !0;
        }
index 8f0587ebd4bd8609b4e97f785f3641f176b01344..087a18245560f467fb059590a91531c4840a4d0d 100644 (file)
@@ -57,7 +57,9 @@ struct pvr2_v4l2_fh {
        struct pvr2_v4l2_fh *vprev;
        wait_queue_head_t wait_data;
        int fw_mode_flag;
-       int prev_input_val;
+       /* Map contiguous ordinal value to input id */
+       unsigned char *input_map;
+       unsigned int input_cnt;
 };
 
 struct pvr2_v4l2 {
@@ -259,14 +261,21 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                struct v4l2_input *vi = (struct v4l2_input *)arg;
                struct v4l2_input tmp;
                unsigned int cnt;
+               int val;
 
                cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
 
                memset(&tmp,0,sizeof(tmp));
                tmp.index = vi->index;
                ret = 0;
-               switch (vi->index) {
+               if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               val = fh->input_map[vi->index];
+               switch (val) {
                case PVR2_CVAL_INPUT_TV:
+               case PVR2_CVAL_INPUT_DTV:
                case PVR2_CVAL_INPUT_RADIO:
                        tmp.type = V4L2_INPUT_TYPE_TUNER;
                        break;
@@ -281,7 +290,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                if (ret < 0) break;
 
                cnt = 0;
-               pvr2_ctrl_get_valname(cptr,vi->index,
+               pvr2_ctrl_get_valname(cptr,val,
                                      tmp.name,sizeof(tmp.name)-1,&cnt);
                tmp.name[cnt] = 0;
 
@@ -303,22 +312,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
        case VIDIOC_G_INPUT:
        {
+               unsigned int idx;
                struct pvr2_ctrl *cptr;
                struct v4l2_input *vi = (struct v4l2_input *)arg;
                int val;
                cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
                val = 0;
                ret = pvr2_ctrl_get_value(cptr,&val);
-               vi->index = val;
+               vi->index = 0;
+               for (idx = 0; idx < fh->input_cnt; idx++) {
+                       if (fh->input_map[idx] == val) {
+                               vi->index = idx;
+                               break;
+                       }
+               }
                break;
        }
 
        case VIDIOC_S_INPUT:
        {
                struct v4l2_input *vi = (struct v4l2_input *)arg;
+               if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+                       ret = -ERANGE;
+                       break;
+               }
                ret = pvr2_ctrl_set_value(
                        pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
-                       vi->index);
+                       fh->input_map[vi->index]);
                break;
        }
 
@@ -858,7 +878,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
 {
        struct pvr2_v4l2_fh *fhp = file->private_data;
        struct pvr2_v4l2 *vp = fhp->vhead;
-       struct pvr2_context *mp = fhp->vhead->channel.mc_head;
        struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
 
        pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
@@ -875,42 +894,30 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
        v4l2_prio_close(&vp->prio, &fhp->prio);
        file->private_data = NULL;
 
-       pvr2_context_enter(mp); do {
-               /* Restore the previous input selection, if it makes sense
-                  to do so. */
-               if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
-                       struct pvr2_ctrl *cp;
-                       int pval;
-                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
-                       pvr2_ctrl_get_value(cp,&pval);
-                       /* Only restore if we're still selecting the radio */
-                       if (pval == PVR2_CVAL_INPUT_RADIO) {
-                               pvr2_ctrl_set_value(cp,fhp->prev_input_val);
-                               pvr2_hdw_commit_ctl(hdw);
-                       }
-               }
-
-               if (fhp->vnext) {
-                       fhp->vnext->vprev = fhp->vprev;
-               } else {
-                       vp->vlast = fhp->vprev;
-               }
-               if (fhp->vprev) {
-                       fhp->vprev->vnext = fhp->vnext;
-               } else {
-                       vp->vfirst = fhp->vnext;
-               }
-               fhp->vnext = NULL;
-               fhp->vprev = NULL;
-               fhp->vhead = NULL;
-               pvr2_channel_done(&fhp->channel);
-               pvr2_trace(PVR2_TRACE_STRUCT,
-                          "Destroying pvr_v4l2_fh id=%p",fhp);
-               kfree(fhp);
-               if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
-                       pvr2_v4l2_destroy_no_lock(vp);
-               }
-       } while (0); pvr2_context_exit(mp);
+       if (fhp->vnext) {
+               fhp->vnext->vprev = fhp->vprev;
+       } else {
+               vp->vlast = fhp->vprev;
+       }
+       if (fhp->vprev) {
+               fhp->vprev->vnext = fhp->vnext;
+       } else {
+               vp->vfirst = fhp->vnext;
+       }
+       fhp->vnext = NULL;
+       fhp->vprev = NULL;
+       fhp->vhead = NULL;
+       pvr2_channel_done(&fhp->channel);
+       pvr2_trace(PVR2_TRACE_STRUCT,
+                  "Destroying pvr_v4l2_fh id=%p",fhp);
+       if (fhp->input_map) {
+               kfree(fhp->input_map);
+               fhp->input_map = NULL;
+       }
+       kfree(fhp);
+       if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+               pvr2_v4l2_destroy_no_lock(vp);
+       }
        return 0;
 }
 
@@ -921,6 +928,9 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
        struct pvr2_v4l2_fh *fhp;
        struct pvr2_v4l2 *vp;
        struct pvr2_hdw *hdw;
+       unsigned int input_mask = 0;
+       unsigned int input_cnt,idx;
+       int ret = 0;
 
        dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
 
@@ -943,32 +953,62 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
        init_waitqueue_head(&fhp->wait_data);
        fhp->dev_info = dip;
 
-       pvr2_context_enter(vp->channel.mc_head); do {
-               pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
-               pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+       pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
 
-               fhp->vnext = NULL;
-               fhp->vprev = vp->vlast;
-               if (vp->vlast) {
-                       vp->vlast->vnext = fhp;
-               } else {
-                       vp->vfirst = fhp;
-               }
-               vp->vlast = fhp;
-               fhp->vhead = vp;
-
-               /* Opening the /dev/radioX device implies a mode switch.
-                  So execute that here.  Note that you can get the
-                  IDENTICAL effect merely by opening the normal video
-                  device and setting the input appropriately. */
-               if (dip->v4l_type == VFL_TYPE_RADIO) {
-                       struct pvr2_ctrl *cp;
-                       cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
-                       pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
-                       pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
-                       pvr2_hdw_commit_ctl(hdw);
-               }
-       } while (0); pvr2_context_exit(vp->channel.mc_head);
+       if (dip->v4l_type == VFL_TYPE_RADIO) {
+               /* Opening device as a radio, legal input selection subset
+                  is just the radio. */
+               input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
+       } else {
+               /* Opening the main V4L device, legal input selection
+                  subset includes all analog inputs. */
+               input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
+                             (1 << PVR2_CVAL_INPUT_TV) |
+                             (1 << PVR2_CVAL_INPUT_COMPOSITE) |
+                             (1 << PVR2_CVAL_INPUT_SVIDEO));
+       }
+       ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
+       if (ret) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input mask error)",
+                          fhp);
+
+               kfree(fhp);
+               return ret;
+       }
+
+       input_mask &= pvr2_hdw_get_input_available(hdw);
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (input_mask & (1 << idx)) input_cnt++;
+       }
+       fhp->input_cnt = input_cnt;
+       fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
+       if (!fhp->input_map) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input map failure)",
+                          fhp);
+               kfree(fhp);
+               return -ENOMEM;
+       }
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (!(input_mask & (1 << idx))) continue;
+               fhp->input_map[input_cnt++] = idx;
+       }
+
+       fhp->vnext = NULL;
+       fhp->vprev = vp->vlast;
+       if (vp->vlast) {
+               vp->vlast->vnext = fhp;
+       } else {
+               vp->vfirst = fhp;
+       }
+       vp->vlast = fhp;
+       fhp->vhead = vp;
 
        fhp->file = file;
        file->private_data = fhp;
@@ -1201,24 +1241,27 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
 
        vp = kzalloc(sizeof(*vp),GFP_KERNEL);
        if (!vp) return vp;
-       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
-       vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
-       if (!(vp->dev_video && vp->dev_radio)) {
-               kfree(vp->dev_video);
-               kfree(vp->dev_radio);
-               kfree(vp);
-               return NULL;
-       }
        pvr2_channel_init(&vp->channel,mnp);
        pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
 
        vp->channel.check_func = pvr2_v4l2_internal_check;
 
        /* register streams */
+       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+       if (!vp->dev_video) goto fail;
        pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
-       pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
+       if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
+           (1 << PVR2_CVAL_INPUT_RADIO)) {
+               vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+               if (!vp->dev_radio) goto fail;
+               pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
+       }
 
        return vp;
+ fail:
+       pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
+       pvr2_v4l2_destroy_no_lock(vp);
+       return 0;
 }
 
 /*
index e0a453a6543d2526c2ba3ef39e1dd86901c8c89e..423fa7c2d0c9b465fa54f0a6cb761ea06e1cd420 100644 (file)
@@ -130,8 +130,8 @@ static int default_fbufs = 3;   /* Default number of frame buffers */
 #ifdef CONFIG_USB_PWC_DEBUG
        int pwc_trace = PWC_DEBUG_LEVEL;
 #endif
-static int power_save = 0;
-static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
+static int power_save;
+static int led_on = 100, led_off; /* defaults to LED that is on while in use */
 static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
        int type;
@@ -159,7 +159,9 @@ static const struct file_operations pwc_fops = {
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
        .ioctl =        pwc_video_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
@@ -487,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        int i;
        unsigned long flags;
 
-       PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
 
        spin_lock_irqsave(&pdev->ptrlock, flags);
        pdev->full_frames = NULL;
@@ -509,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        pdev->fill_image = 0;
        spin_unlock_irqrestore(&pdev->ptrlock, flags);
 
-       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
 }
 
 
@@ -786,8 +788,8 @@ static void pwc_isoc_handler(struct urb *urb)
                } /* ..status == 0 */
                else {
                        /* This is normally not interesting to the user, unless
-                        * you are really debugging something */
-                       static int iso_error = 0;
+                        * you are really debugging something, default = 0 */
+                       static int iso_error;
                        iso_error++;
                        if (iso_error < 20)
                                PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
@@ -1426,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long page, pos = 0;
        int index;
 
-       PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
+       PWC_DEBUG_MEMORY(">> %s\n", __func__);
        pdev = vdev->priv;
        size = vma->vm_end - vma->vm_start;
        start = vma->vm_start;
index 32fbe1ae62519c30d595b545c53e3320a8621f44..1742889874df08c6f944b4b066fa1111fcff2e4a 100644 (file)
@@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
                return -EFAULT;
 
 #ifdef CONFIG_USB_PWC_DEBUG
-       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
                v4l_printk_ioctl(cmd);
+               printk("\n");
+       }
 #endif
 
 
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
new file mode 100644 (file)
index 0000000..7cc8e9b
--- /dev/null
@@ -0,0 +1,1206 @@
+/*
+ * V4L2 Driver for PXA camera host
+ *
+ * Copyright (C) 2006, Sascha Hauer, Pengutronix
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/soc_camera.h>
+
+#include <linux/videodev2.h>
+
+#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/camera.h>
+
+#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
+#define PXA_CAM_DRV_NAME "pxa27x-camera"
+
+#define CICR0_SIM_MP   (0 << 24)
+#define CICR0_SIM_SP   (1 << 24)
+#define CICR0_SIM_MS   (2 << 24)
+#define CICR0_SIM_EP   (3 << 24)
+#define CICR0_SIM_ES   (4 << 24)
+
+#define CICR1_DW_VAL(x)   ((x) & CICR1_DW)         /* Data bus width */
+#define CICR1_PPL_VAL(x)  (((x) << 15) & CICR1_PPL) /* Pixels per line */
+#define CICR1_COLOR_SP_VAL(x)  (((x) << 3) & CICR1_COLOR_SP)   /* color space */
+#define CICR1_RGB_BPP_VAL(x)   (((x) << 7) & CICR1_RGB_BPP)    /* bpp for rgb */
+#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */
+
+#define CICR2_BLW_VAL(x)  (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
+#define CICR2_ELW_VAL(x)  (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
+#define CICR2_HSW_VAL(x)  (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */
+#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */
+#define CICR2_FSW_VAL(x)  (((x) << 0) & CICR2_FSW)  /* Frame stabilization wait count */
+
+#define CICR3_BFW_VAL(x)  (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count  */
+#define CICR3_EFW_VAL(x)  (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */
+#define CICR3_VSW_VAL(x)  (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */
+#define CICR3_LPF_VAL(x)  (((x) << 0) & CICR3_LPF)  /* Lines per frame */
+
+#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \
+                       CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
+                       CICR0_EOFM | CICR0_FOM)
+
+static DEFINE_MUTEX(camera_lock);
+
+/*
+ * Structures
+ */
+enum pxa_camera_active_dma {
+       DMA_Y = 0x1,
+       DMA_U = 0x2,
+       DMA_V = 0x4,
+};
+
+/* descriptor needed for the PXA DMA engine */
+struct pxa_cam_dma {
+       dma_addr_t              sg_dma;
+       struct pxa_dma_desc     *sg_cpu;
+       size_t                  sg_size;
+       int                     sglen;
+};
+
+/* buffer for one video frame */
+struct pxa_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       const struct soc_camera_data_format        *fmt;
+
+       /* our descriptor lists for Y, U and V channels */
+       struct pxa_cam_dma dmas[3];
+
+       int                     inwork;
+
+       enum pxa_camera_active_dma active_dma;
+};
+
+struct pxa_camera_dev {
+       struct device           *dev;
+       /* PXA27x is only supposed to handle one camera on its Quick Capture
+        * interface. If anyone ever builds hardware to enable more than
+        * one camera, they will have to modify this driver too */
+       struct soc_camera_device *icd;
+       struct clk              *clk;
+
+       unsigned int            irq;
+       void __iomem            *base;
+
+       int                     channels;
+       unsigned int            dma_chans[3];
+
+       struct pxacamera_platform_data *pdata;
+       struct resource         *res;
+       unsigned long           platform_flags;
+       unsigned long           platform_mclk_10khz;
+
+       struct list_head        capture;
+
+       spinlock_t              lock;
+
+       struct pxa_buffer       *active;
+       struct pxa_dma_desc     *sg_tail[3];
+};
+
+static const char *pxa_cam_driver_description = "PXA_Camera";
+
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+
+/*
+ *  Videobuf operations
+ */
+static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
+                             unsigned int *size)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
+
+       /* planar capture requires Y, U and V buffers to be page aligned */
+       if (pcdev->channels == 3) {
+               *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
+               *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
+               *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
+       } else {
+               *size = icd->width * icd->height *
+                       ((icd->current_fmt->depth + 7) >> 3);
+       }
+
+       if (0 == *count)
+               *count = 32;
+       while (*size * *count > vid_limit * 1024 * 1024)
+               (*count)--;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       int i;
+
+       BUG_ON(in_interrupt());
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               &buf->vb, buf->vb.baddr, buf->vb.bsize);
+
+       /* This waits until this buffer is out of danger, i.e., until it is no
+        * longer in STATE_QUEUED or STATE_ACTIVE */
+       videobuf_waiton(&buf->vb, 0, 0);
+       videobuf_dma_unmap(vq, dma);
+       videobuf_dma_free(dma);
+
+       for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
+               if (buf->dmas[i].sg_cpu)
+                       dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+                                         buf->dmas[i].sg_cpu,
+                                         buf->dmas[i].sg_dma);
+               buf->dmas[i].sg_cpu = NULL;
+       }
+
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
+                               struct pxa_buffer *buf,
+                               struct videobuf_dmabuf *dma, int channel,
+                               int sglen, int sg_start, int cibr,
+                               unsigned int size)
+{
+       struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
+       int i;
+
+       if (pxa_dma->sg_cpu)
+               dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+                                 pxa_dma->sg_cpu, pxa_dma->sg_dma);
+
+       pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
+       pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+                                            &pxa_dma->sg_dma, GFP_KERNEL);
+       if (!pxa_dma->sg_cpu)
+               return -ENOMEM;
+
+       pxa_dma->sglen = sglen;
+
+       for (i = 0; i < sglen; i++) {
+               int sg_i = sg_start + i;
+               struct scatterlist *sg = dma->sglist;
+               unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len;
+
+               pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
+               pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]);
+
+               /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
+               xfer_len = (min(dma_len, size) + 7) & ~7;
+
+               pxa_dma->sg_cpu[i].dcmd =
+                       DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
+               size -= dma_len;
+               pxa_dma->sg_cpu[i].ddadr =
+                       pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
+       }
+
+       pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP;
+       pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN;
+
+       return 0;
+}
+
+static int pxa_videobuf_prepare(struct videobuf_queue *vq,
+               struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+       int ret;
+       int sglen_y,  sglen_yu = 0, sglen_u = 0, sglen_v = 0;
+       int size_y, size_u = 0, size_v = 0;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       /* Added list head initialization on alloc */
+       WARN_ON(!list_empty(&vb->queue));
+
+#ifdef DEBUG
+       /* This can be useful if you want to see if we actually fill
+        * the buffer with something */
+       memset((void *)vb->baddr, 0xaa, vb->bsize);
+#endif
+
+       BUG_ON(NULL == icd->current_fmt);
+
+       /* I think, in buf_prepare you only have to protect global data,
+        * the actual buffer is yours */
+       buf->inwork = 1;
+
+       if (buf->fmt    != icd->current_fmt ||
+           vb->width   != icd->width ||
+           vb->height  != icd->height ||
+           vb->field   != field) {
+               buf->fmt        = icd->current_fmt;
+               vb->width       = icd->width;
+               vb->height      = icd->height;
+               vb->field       = field;
+               vb->state       = VIDEOBUF_NEEDS_INIT;
+       }
+
+       vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+       if (0 != vb->baddr && vb->bsize < vb->size) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (vb->state == VIDEOBUF_NEEDS_INIT) {
+               unsigned int size = vb->size;
+               struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+
+               ret = videobuf_iolock(vq, vb, NULL);
+               if (ret)
+                       goto fail;
+
+               if (pcdev->channels == 3) {
+                       /* FIXME the calculations should be more precise */
+                       sglen_y = dma->sglen / 2;
+                       sglen_u = sglen_v = dma->sglen / 4 + 1;
+                       sglen_yu = sglen_y + sglen_u;
+                       size_y = size / 2;
+                       size_u = size_v = size / 4;
+               } else {
+                       sglen_y = dma->sglen;
+                       size_y = size;
+               }
+
+               /* init DMA for Y channel */
+               ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y,
+                                          0, 0x28, size_y);
+
+               if (ret) {
+                       dev_err(pcdev->dev,
+                               "DMA initialization for Y/RGB failed\n");
+                       goto fail;
+               }
+
+               if (pcdev->channels == 3) {
+                       /* init DMA for U channel */
+                       ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
+                                                  sglen_y, 0x30, size_u);
+                       if (ret) {
+                               dev_err(pcdev->dev,
+                                       "DMA initialization for U failed\n");
+                               goto fail_u;
+                       }
+
+                       /* init DMA for V channel */
+                       ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v,
+                                                  sglen_yu, 0x38, size_v);
+                       if (ret) {
+                               dev_err(pcdev->dev,
+                                       "DMA initialization for V failed\n");
+                               goto fail_v;
+                       }
+               }
+
+               vb->state = VIDEOBUF_PREPARED;
+       }
+
+       buf->inwork = 0;
+       buf->active_dma = DMA_Y;
+       if (pcdev->channels == 3)
+               buf->active_dma |= DMA_U | DMA_V;
+
+       return 0;
+
+fail_v:
+       dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+                         buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
+fail_u:
+       dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+                         buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
+fail:
+       free_buffer(vq, buf);
+out:
+       buf->inwork = 0;
+       return ret;
+}
+
+static void pxa_videobuf_queue(struct videobuf_queue *vq,
+                              struct videobuf_buffer *vb)
+{
+       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+       struct pxa_buffer *active;
+       unsigned long flags;
+       int i;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+       spin_lock_irqsave(&pcdev->lock, flags);
+
+       list_add_tail(&vb->queue, &pcdev->capture);
+
+       vb->state = VIDEOBUF_ACTIVE;
+       active = pcdev->active;
+
+       if (!active) {
+               CIFR |= CIFR_RESET_F;
+
+               for (i = 0; i < pcdev->channels; i++) {
+                       DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+                       pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
+               }
+
+               pcdev->active = buf;
+               CICR0 |= CICR0_ENB;
+       } else {
+               struct pxa_cam_dma *buf_dma;
+               struct pxa_cam_dma *act_dma;
+               int nents;
+
+               for (i = 0; i < pcdev->channels; i++) {
+                       buf_dma = &buf->dmas[i];
+                       act_dma = &active->dmas[i];
+                       nents = buf_dma->sglen;
+
+                       /* Stop DMA engine */
+                       DCSR(pcdev->dma_chans[i]) = 0;
+
+                       /* Add the descriptors we just initialized to
+                          the currently running chain */
+                       pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
+                       pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
+
+                       /* Setup a dummy descriptor with the DMA engines current
+                        * state
+                        */
+                       buf_dma->sg_cpu[nents].dsadr =
+                               pcdev->res->start + 0x28 + i*8; /* CIBRx */
+                       buf_dma->sg_cpu[nents].dtadr =
+                               DTADR(pcdev->dma_chans[i]);
+                       buf_dma->sg_cpu[nents].dcmd =
+                               DCMD(pcdev->dma_chans[i]);
+
+                       if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) {
+                               /* The DMA engine is on the last
+                                  descriptor, set the next descriptors
+                                  address to the descriptors we just
+                                  initialized */
+                               buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma;
+                       } else {
+                               buf_dma->sg_cpu[nents].ddadr =
+                                       DDADR(pcdev->dma_chans[i]);
+                       }
+
+                       /* The next descriptor is the dummy descriptor */
+                       DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents *
+                               sizeof(struct pxa_dma_desc);
+
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+               }
+       }
+
+       spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void pxa_videobuf_release(struct videobuf_queue *vq,
+                                struct videobuf_buffer *vb)
+{
+       struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
+#ifdef DEBUG
+       struct soc_camera_device *icd = vq->priv_data;
+
+       dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       switch (vb->state) {
+       case VIDEOBUF_ACTIVE:
+               dev_dbg(&icd->dev, "%s (active)\n", __func__);
+               break;
+       case VIDEOBUF_QUEUED:
+               dev_dbg(&icd->dev, "%s (queued)\n", __func__);
+               break;
+       case VIDEOBUF_PREPARED:
+               dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
+               break;
+       default:
+               dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
+               break;
+       }
+#endif
+
+       free_buffer(vq, buf);
+}
+
+static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
+                             struct videobuf_buffer *vb,
+                             struct pxa_buffer *buf)
+{
+       /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
+       list_del_init(&vb->queue);
+       vb->state = VIDEOBUF_DONE;
+       do_gettimeofday(&vb->ts);
+       vb->field_count++;
+       wake_up(&vb->done);
+
+       if (list_empty(&pcdev->capture)) {
+               pcdev->active = NULL;
+               DCSR(pcdev->dma_chans[0]) = 0;
+               DCSR(pcdev->dma_chans[1]) = 0;
+               DCSR(pcdev->dma_chans[2]) = 0;
+               CICR0 &= ~CICR0_ENB;
+               return;
+       }
+
+       pcdev->active = list_entry(pcdev->capture.next,
+                                  struct pxa_buffer, vb.queue);
+}
+
+static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+                              enum pxa_camera_active_dma act_dma)
+{
+       struct pxa_buffer *buf;
+       unsigned long flags;
+       u32 status, camera_status, overrun;
+       struct videobuf_buffer *vb;
+
+       spin_lock_irqsave(&pcdev->lock, flags);
+
+       status = DCSR(channel);
+       DCSR(channel) = status | DCSR_ENDINTR;
+
+       if (status & DCSR_BUSERR) {
+               dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
+               goto out;
+       }
+
+       if (!(status & DCSR_ENDINTR)) {
+               dev_err(pcdev->dev, "Unknown DMA IRQ source, "
+                       "status: 0x%08x\n", status);
+               goto out;
+       }
+
+       if (!pcdev->active) {
+               dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n");
+               goto out;
+       }
+
+       camera_status = CISR;
+       overrun = CISR_IFO_0;
+       if (pcdev->channels == 3)
+               overrun |= CISR_IFO_1 | CISR_IFO_2;
+       if (camera_status & overrun) {
+               dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status);
+               /* Stop the Capture Interface */
+               CICR0 &= ~CICR0_ENB;
+               /* Stop DMA */
+               DCSR(channel) = 0;
+               /* Reset the FIFOs */
+               CIFR |= CIFR_RESET_F;
+               /* Enable End-Of-Frame Interrupt */
+               CICR0 &= ~CICR0_EOFM;
+               /* Restart the Capture Interface */
+               CICR0 |= CICR0_ENB;
+               goto out;
+       }
+
+       vb = &pcdev->active->vb;
+       buf = container_of(vb, struct pxa_buffer, vb);
+       WARN_ON(buf->inwork || list_empty(&vb->queue));
+       dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+               vb, vb->baddr, vb->bsize);
+
+       buf->active_dma &= ~act_dma;
+       if (!buf->active_dma)
+               pxa_camera_wakeup(pcdev, vb, buf);
+
+out:
+       spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void pxa_camera_dma_irq_y(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(int channel, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       pxa_camera_dma_irq(channel, pcdev, DMA_V);
+}
+
+static struct videobuf_queue_ops pxa_videobuf_ops = {
+       .buf_setup      = pxa_videobuf_setup,
+       .buf_prepare    = pxa_videobuf_prepare,
+       .buf_queue      = pxa_videobuf_queue,
+       .buf_release    = pxa_videobuf_release,
+};
+
+static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
+{
+       unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
+       unsigned long div;
+       unsigned long lcdclk;
+
+       lcdclk = clk_get_rate(pcdev->clk) / 10000;
+
+       /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here
+        * they get a nice Oops */
+       div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1;
+
+       dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, "
+               "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div);
+
+       return div;
+}
+
+static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
+{
+       struct pxacamera_platform_data *pdata = pcdev->pdata;
+       u32 cicr4 = 0;
+
+       dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
+               pcdev, pdata);
+
+       if (pdata && pdata->init) {
+               dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
+               pdata->init(pcdev->dev);
+       }
+
+       if (pdata && pdata->power) {
+               dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
+               pdata->power(pcdev->dev, 1);
+       }
+
+       if (pdata && pdata->reset) {
+               dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
+                       __func__);
+               pdata->reset(pcdev->dev, 1);
+       }
+
+       CICR0 = 0x3FF;   /* disable all interrupts */
+
+       if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+               cicr4 |= CICR4_PCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
+               cicr4 |= CICR4_MCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_PCP)
+               cicr4 |= CICR4_PCP;
+       if (pcdev->platform_flags & PXA_CAMERA_HSP)
+               cicr4 |= CICR4_HSP;
+       if (pcdev->platform_flags & PXA_CAMERA_VSP)
+               cicr4 |= CICR4_VSP;
+
+       CICR4 = mclk_get_divisor(pcdev) | cicr4;
+
+       clk_enable(pcdev->clk);
+}
+
+static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
+{
+       struct pxacamera_platform_data *board = pcdev->pdata;
+
+       clk_disable(pcdev->clk);
+
+       if (board && board->reset) {
+               dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
+                       __func__);
+               board->reset(pcdev->dev, 0);
+       }
+
+       if (board && board->power) {
+               dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
+               board->power(pcdev->dev, 0);
+       }
+}
+
+static irqreturn_t pxa_camera_irq(int irq, void *data)
+{
+       struct pxa_camera_dev *pcdev = data;
+       unsigned int status = CISR;
+
+       dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status);
+
+       if (!status)
+               return IRQ_NONE;
+
+       CISR = status;
+
+       if (status & CISR_EOF) {
+               int i;
+               for (i = 0; i < pcdev->channels; i++) {
+                       DDADR(pcdev->dma_chans[i]) =
+                               pcdev->active->dmas[i].sg_dma;
+                       DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+               }
+               CICR0 |= CICR0_EOFM;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/* The following two functions absolutely depend on the fact, that
+ * there can be only one camera on PXA quick capture interface */
+static int pxa_camera_add_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       int ret;
+
+       mutex_lock(&camera_lock);
+
+       if (pcdev->icd) {
+               ret = -EBUSY;
+               goto ebusy;
+       }
+
+       dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
+                icd->devnum);
+
+       pxa_camera_activate(pcdev);
+       ret = icd->ops->init(icd);
+
+       if (!ret)
+               pcdev->icd = icd;
+
+ebusy:
+       mutex_unlock(&camera_lock);
+
+       return ret;
+}
+
+static void pxa_camera_remove_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       BUG_ON(icd != pcdev->icd);
+
+       dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n",
+                icd->devnum);
+
+       /* disable capture, disable interrupts */
+       CICR0 = 0x3ff;
+
+       /* Stop DMA engine */
+       DCSR(pcdev->dma_chans[0]) = 0;
+       DCSR(pcdev->dma_chans[1]) = 0;
+       DCSR(pcdev->dma_chans[2]) = 0;
+
+       icd->ops->release(icd);
+
+       pxa_camera_deactivate(pcdev);
+
+       pcdev->icd = NULL;
+}
+
+static int test_platform_param(struct pxa_camera_dev *pcdev,
+                              unsigned char buswidth, unsigned long *flags)
+{
+       /*
+        * Platform specified synchronization and pixel clock polarities are
+        * only a recommendation and are only used during probing. The PXA270
+        * quick capture interface supports both.
+        */
+       *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
+                 SOCAM_MASTER : SOCAM_SLAVE) |
+               SOCAM_HSYNC_ACTIVE_HIGH |
+               SOCAM_HSYNC_ACTIVE_LOW |
+               SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_VSYNC_ACTIVE_LOW |
+               SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_PCLK_SAMPLE_FALLING;
+
+       /* If requested data width is supported by the platform, use it */
+       switch (buswidth) {
+       case 10:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_10;
+               break;
+       case 9:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_9;
+               break;
+       case 8:
+               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
+                       return -EINVAL;
+               *flags |= SOCAM_DATAWIDTH_8;
+       }
+
+       return 0;
+}
+
+static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
+       u32 cicr0, cicr1, cicr4 = 0;
+       int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+
+       if (ret < 0)
+               return ret;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+
+       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+       if (!common_flags)
+               return -EINVAL;
+
+       pcdev->channels = 1;
+
+       /* Make choises, based on platform preferences */
+       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+               if (pcdev->platform_flags & PXA_CAMERA_HSP)
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+               if (pcdev->platform_flags & PXA_CAMERA_VSP)
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+               else
+                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+       }
+
+       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
+           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+               if (pcdev->platform_flags & PXA_CAMERA_PCP)
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+               else
+                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+       }
+
+       ret = icd->ops->set_bus_param(icd, common_flags);
+       if (ret < 0)
+               return ret;
+
+       /* Datawidth is now guaranteed to be equal to one of the three values.
+        * We fix bit-per-pixel equal to data-width... */
+       switch (common_flags & SOCAM_DATAWIDTH_MASK) {
+       case SOCAM_DATAWIDTH_10:
+               icd->buswidth = 10;
+               dw = 4;
+               bpp = 0x40;
+               break;
+       case SOCAM_DATAWIDTH_9:
+               icd->buswidth = 9;
+               dw = 3;
+               bpp = 0x20;
+               break;
+       default:
+               /* Actually it can only be 8 now,
+                * default is just to silence compiler warnings */
+       case SOCAM_DATAWIDTH_8:
+               icd->buswidth = 8;
+               dw = 2;
+               bpp = 0;
+       }
+
+       if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+               cicr4 |= CICR4_PCLK_EN;
+       if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
+               cicr4 |= CICR4_MCLK_EN;
+       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+               cicr4 |= CICR4_PCP;
+       if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+               cicr4 |= CICR4_HSP;
+       if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+               cicr4 |= CICR4_VSP;
+
+       cicr0 = CICR0;
+       if (cicr0 & CICR0_ENB)
+               CICR0 = cicr0 & ~CICR0_ENB;
+
+       cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
+
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_YUV422P:
+               pcdev->channels = 3;
+               cicr1 |= CICR1_YCBCR_F;
+       case V4L2_PIX_FMT_YUYV:
+               cicr1 |= CICR1_COLOR_SP_VAL(2);
+               break;
+       case V4L2_PIX_FMT_RGB555:
+               cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
+                       CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
+               break;
+       }
+
+       CICR1 = cicr1;
+       CICR2 = 0;
+       CICR3 = CICR3_LPF_VAL(icd->height - 1) |
+               CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
+       CICR4 = mclk_get_divisor(pcdev) | cicr4;
+
+       /* CIF interrupts are not used, only DMA */
+       CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
+                CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) |
+               CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB);
+
+       return 0;
+}
+
+static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+       unsigned long bus_flags, camera_flags;
+       int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+
+       if (ret < 0)
+               return ret;
+
+       camera_flags = icd->ops->query_bus_param(icd);
+
+       return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
+}
+
+static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
+                                 __u32 pixfmt, struct v4l2_rect *rect)
+{
+       return icd->ops->set_fmt_cap(icd, pixfmt, rect);
+}
+
+static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
+                                 struct v4l2_format *f)
+{
+       /* limit to pxa hardware capabilities */
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.height > 2048)
+               f->fmt.pix.height = 2048;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > 2048)
+               f->fmt.pix.width = 2048;
+       f->fmt.pix.width &= ~0x01;
+
+       /* limit to sensor capabilities */
+       return icd->ops->try_fmt_cap(icd, f);
+}
+
+static int pxa_camera_reqbufs(struct soc_camera_file *icf,
+                             struct v4l2_requestbuffers *p)
+{
+       int i;
+
+       /* This is for locking debugging only. I removed spinlocks and now I
+        * check whether .prepare is ever called on a linked buffer, or whether
+        * a dma IRQ can occur for an in-work or unlinked buffer. Until now
+        * it hadn't triggered */
+       for (i = 0; i < p->count; i++) {
+               struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
+                                                     struct pxa_buffer, vb);
+               buf->inwork = 0;
+               INIT_LIST_HEAD(&buf->vb.queue);
+       }
+
+       return 0;
+}
+
+static unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct pxa_buffer *buf;
+
+       buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer,
+                        vb.stream);
+
+       poll_wait(file, &buf->vb.done, pt);
+
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               return POLLIN|POLLRDNORM;
+
+       return 0;
+}
+
+static int pxa_camera_querycap(struct soc_camera_host *ici,
+                              struct v4l2_capability *cap)
+{
+       /* cap->name is set by the firendly caller:-> */
+       strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
+       cap->version = PXA_CAM_VERSION_CODE;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
+{
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icf->icd->dev.parent);
+       struct pxa_camera_dev *pcdev = ici->priv;
+
+       return &pcdev->lock;
+}
+
+static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
+       .owner          = THIS_MODULE,
+       .add            = pxa_camera_add_device,
+       .remove         = pxa_camera_remove_device,
+       .set_fmt_cap    = pxa_camera_set_fmt_cap,
+       .try_fmt_cap    = pxa_camera_try_fmt_cap,
+       .reqbufs        = pxa_camera_reqbufs,
+       .poll           = pxa_camera_poll,
+       .querycap       = pxa_camera_querycap,
+       .try_bus_param  = pxa_camera_try_bus_param,
+       .set_bus_param  = pxa_camera_set_bus_param,
+       .spinlock_alloc = pxa_camera_spinlock_alloc,
+};
+
+/* Should be allocated dynamically too, but we have only one. */
+static struct soc_camera_host pxa_soc_camera_host = {
+       .drv_name               = PXA_CAM_DRV_NAME,
+       .vbq_ops                = &pxa_videobuf_ops,
+       .msize                  = sizeof(struct pxa_buffer),
+       .ops                    = &pxa_soc_camera_host_ops,
+};
+
+static int pxa_camera_probe(struct platform_device *pdev)
+{
+       struct pxa_camera_dev *pcdev;
+       struct resource *res;
+       void __iomem *base;
+       unsigned int irq;
+       int err = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!res || !irq) {
+               err = -ENODEV;
+               goto exit;
+       }
+
+       pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+       if (!pcdev) {
+               dev_err(&pdev->dev, "Could not allocate pcdev\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       pcdev->clk = clk_get(&pdev->dev, "CAMCLK");
+       if (IS_ERR(pcdev->clk)) {
+               err = PTR_ERR(pcdev->clk);
+               goto exit_kfree;
+       }
+
+       dev_set_drvdata(&pdev->dev, pcdev);
+       pcdev->res = res;
+
+       pcdev->pdata = pdev->dev.platform_data;
+       pcdev->platform_flags = pcdev->pdata->flags;
+       if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
+                       PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
+               /* Platform hasn't set available data widths. This is bad.
+                * Warn and use a default. */
+               dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
+                        "data widths, using default 10 bit\n");
+               pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
+       }
+       pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz;
+       if (!pcdev->platform_mclk_10khz) {
+               dev_warn(&pdev->dev,
+                        "mclk_10khz == 0! Please, fix your platform data. "
+                        "Using default 20MHz\n");
+               pcdev->platform_mclk_10khz = 2000;
+       }
+
+       INIT_LIST_HEAD(&pcdev->capture);
+       spin_lock_init(&pcdev->lock);
+
+       /*
+        * Request the regions.
+        */
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               PXA_CAM_DRV_NAME)) {
+               err = -EBUSY;
+               goto exit_clk;
+       }
+
+       base = ioremap(res->start, res->end - res->start + 1);
+       if (!base) {
+               err = -ENOMEM;
+               goto exit_release;
+       }
+       pcdev->irq = irq;
+       pcdev->base = base;
+       pcdev->dev = &pdev->dev;
+
+       /* request dma */
+       pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_y, pcdev);
+       if (pcdev->dma_chans[0] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for Y\n");
+               err = -ENOMEM;
+               goto exit_iounmap;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+
+       pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_u, pcdev);
+       if (pcdev->dma_chans[1] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for U\n");
+               err = -ENOMEM;
+               goto exit_free_dma_y;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+
+       pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
+                                             pxa_camera_dma_irq_v, pcdev);
+       if (pcdev->dma_chans[0] < 0) {
+               dev_err(pcdev->dev, "Can't request DMA for V\n");
+               err = -ENOMEM;
+               goto exit_free_dma_u;
+       }
+       dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
+
+       DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+       DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+       DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
+
+       /* request irq */
+       err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
+                         pcdev);
+       if (err) {
+               dev_err(pcdev->dev, "Camera interrupt register failed \n");
+               goto exit_free_dma;
+       }
+
+       pxa_soc_camera_host.priv        = pcdev;
+       pxa_soc_camera_host.dev.parent  = &pdev->dev;
+       pxa_soc_camera_host.nr          = pdev->id;
+       err = soc_camera_host_register(&pxa_soc_camera_host);
+       if (err)
+               goto exit_free_irq;
+
+       return 0;
+
+exit_free_irq:
+       free_irq(pcdev->irq, pcdev);
+exit_free_dma:
+       pxa_free_dma(pcdev->dma_chans[2]);
+exit_free_dma_u:
+       pxa_free_dma(pcdev->dma_chans[1]);
+exit_free_dma_y:
+       pxa_free_dma(pcdev->dma_chans[0]);
+exit_iounmap:
+       iounmap(base);
+exit_release:
+       release_mem_region(res->start, res->end - res->start + 1);
+exit_clk:
+       clk_put(pcdev->clk);
+exit_kfree:
+       kfree(pcdev);
+exit:
+       return err;
+}
+
+static int __devexit pxa_camera_remove(struct platform_device *pdev)
+{
+       struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       clk_put(pcdev->clk);
+
+       pxa_free_dma(pcdev->dma_chans[0]);
+       pxa_free_dma(pcdev->dma_chans[1]);
+       pxa_free_dma(pcdev->dma_chans[2]);
+       free_irq(pcdev->irq, pcdev);
+
+       soc_camera_host_unregister(&pxa_soc_camera_host);
+
+       iounmap(pcdev->base);
+
+       res = pcdev->res;
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       kfree(pcdev);
+
+       dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
+
+       return 0;
+}
+
+static struct platform_driver pxa_camera_driver = {
+       .driver         = {
+               .name   = PXA_CAM_DRV_NAME,
+       },
+       .probe          = pxa_camera_probe,
+       .remove         = __exit_p(pxa_camera_remove),
+};
+
+
+static int __devinit pxa_camera_init(void)
+{
+       return platform_driver_register(&pxa_camera_driver);
+}
+
+static void __exit pxa_camera_exit(void)
+{
+       return platform_driver_unregister(&pxa_camera_driver);
+}
+
+module_init(pxa_camera_init);
+module_exit(pxa_camera_exit);
+
+MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index f55d6e85f20f34c59d93e4ae9a5f70c59ecd0a32..ec8c65dc8408506ae02786a4dc7e2e982f63f21f 100644 (file)
@@ -701,7 +701,9 @@ static const struct file_operations saa_fops = {
        .open           = saa5249_open,
        .release        = saa5249_release,
        .ioctl          = saa5249_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 72e344a12c798e86a5ca06db54c4c7a8059e423b..716ee7f64df3c017deffdd15dbf899e48fb8840c 100644 (file)
@@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = {
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
-static unsigned int debug = 0;
-static unsigned int xtal = 0;
-static unsigned int rbds = 0;
-static unsigned int plvl = 0;
+static unsigned int debug;
+static unsigned int xtal;
+static unsigned int rbds;
+static unsigned int plvl;
 static unsigned int bufblocks = 100;
 
 module_param(debug, int, 0644);
index 1df2602cd1842c40d0ed1a9ca56d2793221e8a0c..4aa82b310708c768140e50b698e81932d21e94a0 100644 (file)
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
 #include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index a0772c53bb1f5e78c8dd2a00b5dd529664805683..96c3d4357722fb32d279a8f63aae8a7318c6b7d5 100644 (file)
@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index bf91a4faa706f154903b9be9f7069fb9e55ded2a..e79075533beb2bcc9ffc90825d8777e5cf0c033f 100644 (file)
@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(x) (x)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 41e5e518a47e21926245fc8deca0d115f2edf8dc..416d05d4a969088d02d2f1c5a319de4fb215fe68 100644 (file)
@@ -57,7 +57,7 @@ MODULE_AUTHOR(  "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
                "Hans Verkuil, Mauro Carvalho Chehab");
 MODULE_LICENSE("GPL");
 
-static int debug = 0;
+static int debug;
 module_param(debug, bool, 0644);
 
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -957,7 +957,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
 
                if (std == V4L2_STD_PAL_M) {
                        reg |= 0x30;
-               } else if (std == V4L2_STD_PAL_N) {
+               } else if (std == V4L2_STD_PAL_Nc) {
                        reg |= 0x20;
                } else if (std == V4L2_STD_PAL_60) {
                        reg |= 0x10;
index 80bf9118785624bdbdbbc68e8c46545f47a6b608..cedb988574bdbcf65023d2ddc777c046ff64fd17 100644 (file)
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
 
 #include <linux/video_decoder.h>
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, " Set the default Debug level.  Default: 0 (Off) - (0-1)");
 
index 96bc3b1298a2564389b262e843b49622da4fde44..e086f14d56639ef458e1c69be6dd83eaa7d50f57 100644 (file)
@@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_TDA827X if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB cards based on the
          Philips saa7134 chip.
index ec6bdb9680a3b2289975e3c8f5b1554e7b0f4ff7..ba3082422a01915dce20bce15832c495e9555d89 100644 (file)
@@ -31,7 +31,7 @@
 #include "saa7134.h"
 #include "saa7134-reg.h"
 
-static unsigned int debug  = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
 
@@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
        /* release the old buffer */
        if (substream->runtime->dma_area) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                substream->runtime->dma_area = NULL;
        }
@@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
                return err;
        }
 
-       if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
+       if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
                dsp_buffer_free(dev);
                return err;
        }
        if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                return err;
        }
@@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
                                                dev->dmasound.dma.sglen,
                                                0))) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                return err;
        }
@@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
 
        if (substream->runtime->dma_area) {
                saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
+               videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
                dsp_buffer_free(dev);
                substream->runtime->dma_area = NULL;
        }
index 6f5744286e8c2044aece263c1e4d65ff66a5c629..98375955a84b7c42e62b34a83cf76dc358d0c52f 100644 (file)
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
+#include "tuner-xc2028.h"
 #include <media/v4l2-common.h>
 #include <media/tveeprom.h>
+#include "tea5767.h"
 
 /* commly used strings */
 static char name_mute[]    = "mute";
@@ -1046,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_MANLI_MTV002] = {
                /* Ognjen Nastic <ognjen@logosoft.ba> */
-               .name           = "Manli MuchTV M-TV002/Behold TV 403 FM",
+               .name           = "Manli MuchTV M-TV002",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_PAL,
                .radio_type     = UNSET,
@@ -1073,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_MANLI_MTV001] = {
                /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
-               .name           = "Manli MuchTV M-TV001/Behold TV 401",
+               .name           = "Manli MuchTV M-TV001",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_PAL,
                .radio_type     = UNSET,
@@ -2195,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_BEHOLD_409FM] = {
                /* <http://tuner.beholder.ru>, Sergey <skiv@orel.ru> */
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 409 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -2202,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                          .name = name_tv,
                          .vmux = 3,
@@ -2908,15 +2915,13 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_MD7134_BRIDGE_2] = {
-               /* This card has two saa7134 chips on it,
-                  but only one of them is currently working.
-                  The programming for the primary decoder is
-                  in SAA7134_BOARD_MD7134 */
+               /* The second saa7134 on this card only serves as DVB-S host bridge */
                .name           = "Medion 7134 Bridge #2",
                .audio_clock    = 0x00187de7,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
        },
        [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
                .name           = "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB",
@@ -3330,7 +3335,7 @@ struct saa7134_board saa7134_boards[] = {
   /*   Juan Pablo Sormani <sorman@gmail.com> */
                .name           = "Encore ENLTV-FM",
                .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_ATSC,
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
@@ -3575,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_401] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 401",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3601,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_403] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 403",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3623,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_403FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 403 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FQ1216ME,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3649,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_405] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 405",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3656,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3673,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_BEHOLD_405FM] = {
                /* Sergey <skiv@orel.ru> */
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 405 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3680,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3700,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_407] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 407",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3707,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask = 0xc0c000,
+               .gpiomask       = 0x00008000,
                .inputs = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3727,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_407FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 407 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3734,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask = 0xc0c000,
+               .gpiomask       = 0x00008000,
                .inputs = {{
                        .name = name_svideo,
                        .vmux = 8,
@@ -3759,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_409] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 409",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3766,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3782,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_BEHOLD_505FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 505 FM/RDS",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3789,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3813,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_507_9FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3820,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -3840,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
                .name           = "Beholder BeholdTV Columbus TVFM",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_ALPS_TSBE5_PAL,
@@ -3847,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x000A8004,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
                        .amux = TV,
                        .tv   = 1,
-               },{
+                       .gpio = 0x000A8004,
+               }, {
                        .name = name_comp1,
                        .vmux = 1,
                        .amux = LINE1,
-               },{
+                       .gpio = 0x000A8000,
+               }, {
                        .name = name_svideo,
                        .vmux = 8,
                        .amux = LINE1,
-               }},
+                       .gpio = 0x000A8000,
+               } },
                .radio = {
                        .name = name_radio,
                        .amux = LINE2,
+                       .gpio = 0x000A8000,
                },
        },
        [SAA7134_BOARD_BEHOLD_607_9FM] = {
@@ -3992,6 +4032,221 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x6000,
                },
        },
+       [SAA7134_BOARD_PHILIPS_SNAKE] = {
+               .name           = "NXP Snake DVB-S reference design",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_CREATIX_CTX953] = {
+               .name         = "Medion/Creatix CTX953 Hybrid",
+               .audio_clock  = 0x00187de7,
+               .tuner_type   = TUNER_PHILIPS_TDA8290,
+               .radio_type   = UNSET,
+               .tuner_addr   = ADDR_UNSET,
+               .radio_addr   = ADDR_UNSET,
+               .tuner_config = 0,
+               .mpeg         = SAA7134_MPEG_DVB,
+               .inputs       = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = {
+               .name           = "MSI TV@nywhere A/D v1.1",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x0200000,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = {
+               .name           = "AVerMedia Cardbus TV/Radio (E506R)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+                /*
+                   TODO:
+                .mpeg           = SAA7134_MPEG_DVB,
+                */
+
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                }, {
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE2,
+                }, {
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE1,
+                } },
+                .radio = {
+                        .name = name_radio,
+                        .amux = TV,
+                },
+       },
+       [SAA7134_BOARD_AVERMEDIA_A16D] = {
+               .name           = "AVerMedia Hybrid TV/Radio (A16D)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_M115] = {
+               .name           = "Avermedia M115",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+       },
+       [SAA7134_BOARD_VIDEOMATE_T750] = {
+               /* John Newbigin <jn@it.swin.edu.au> */
+               .name           = "Compro VideoMate T750",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               }
+       },
+       [SAA7134_BOARD_AVERMEDIA_A700_PRO] = {
+               /* Matthias Schwarzott <zzam@gentoo.org> */
+               .name           = "Avermedia DVB-S Pro A700",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /* no DVB support for now */
+               /* .mpeg           = SAA7134_MPEG_DVB, */
+               .inputs         = { {
+                       .name = name_comp,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = {
+               /* Matthias Schwarzott <zzam@gentoo.org> */
+               .name           = "Avermedia DVB-S Hybrid+FM A700",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT, /* TUNER_XC2028 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /* no DVB support for now */
+               /* .mpeg           = SAA7134_MPEG_DVB, */
+               .inputs         = { {
+                       .name = name_comp,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               } },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -4223,6 +4478,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subdevice    = 0xa70b,
                .driver_data  = SAA7134_BOARD_MD2819,
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa7a1,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A700_PRO,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa7a2,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A700_HYBRID,
+       }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
                .subvendor    = 0x1461, /* Avermedia Technologies Inc */
@@ -4942,7 +5209,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x1822, /*Twinhan Technology Co. Ltd*/
                .subdevice    = 0x0022,
                .driver_data  = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0010, /* Medion version CTX953_V.1.4.3 */
+               .driver_data  = SAA7134_BOARD_CREATIX_CTX953,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1462, /* MSI */
+               .subdevice    = 0x8625, /* TV@nywhere A/D v1.1 */
+               .driver_data  = SAA7134_BOARD_MSI_TVANYWHERE_AD11,
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf436,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_506,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf936,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A16D,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa836,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M115,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc900,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
+       }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -4998,6 +5301,77 @@ static void board_flyvideo(struct saa7134_dev *dev)
               dev->name, dev->name, dev->name);
 }
 
+static int saa7134_xc2028_callback(struct saa7134_dev *dev,
+                                  int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+               mdelay(250);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0);
+               mdelay(250);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+               mdelay(250);
+               saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
+               saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
+               saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
+               saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
+               saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
+                          0x0001e000, 0x0001e000);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+
+static int saa7134_tda8290_callback(struct saa7134_dev *dev,
+                                   int command, int arg)
+{
+       u8 sync_control;
+
+       switch (command) {
+       case 0: /* switch LNA gain through GPIO 22*/
+               saa7134_set_gpio(dev, 22, arg) ;
+               break;
+       case 1: /* vsync output at GPIO22. 50 / 60Hz */
+               saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
+               saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
+               if (arg == 1)
+                       sync_control = 11;
+               else
+                       sync_control = 17;
+               saa_writeb(SAA7134_VGATE_START, sync_control);
+               saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
+               saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int saa7134_tuner_callback(void *priv, int command, int arg)
+{
+       struct saa7134_dev *dev = priv;
+       if (dev != NULL) {
+               switch (dev->tuner_type) {
+               case TUNER_PHILIPS_TDA8290:
+                       return saa7134_tda8290_callback(dev, command, arg);
+               case TUNER_XC2028:
+                       return saa7134_xc2028_callback(dev, command, arg);
+               }
+       } else {
+               printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
+               return -EINVAL;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(saa7134_tuner_callback);
+
 /* ----------------------------------------------------------- */
 
 static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
@@ -5067,6 +5441,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+       case SAA7134_BOARD_VIDEOMATE_T750:
        case SAA7134_BOARD_MANLI_MTV001:
        case SAA7134_BOARD_MANLI_MTV002:
        case SAA7134_BOARD_BEHOLD_409FM:
@@ -5133,11 +5508,29 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
                break;
        case SAA7134_BOARD_AVERMEDIA_CARDBUS:
-       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+       case SAA7134_BOARD_AVERMEDIA_M115:
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               /* power-down tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
+               msleep(10);
                /* power-up tuner chip */
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0xffffffff);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
-               msleep(1);
+               msleep(10);
+               break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               /* power-down tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
+               msleep(10);
+               /* power-up tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
+               msleep(10);
+               /* remote via GPIO */
+               dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_RTD_VFG7350:
 
@@ -5160,7 +5553,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                dev->has_remote = SAA7134_REMOTE_I2C;
                break;
        case SAA7134_BOARD_AVERMEDIA_A169_B:
-       case SAA7134_BOARD_MD7134_BRIDGE_2:
                printk("%s: %s: dual saa713x broadcast decoders\n"
                       "%s: Sorry, none of the inputs to this chip are supported yet.\n"
                       "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
@@ -5172,6 +5564,15 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
                break;
+       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+               /* write windows gpio values */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
+               printk("%s: %s: hybrid analog/dvb card\n"
+                      "%s: Sorry, only the analog inputs are supported for now.\n",
+                       dev->name, card(dev).name, dev->name);
+               break;
        }
        return 0;
 }
@@ -5200,11 +5601,16 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                dev->tuner_type = saa7134_boards[dev->board].tuner_type;
 
                if (TUNER_ABSENT != dev->tuner_type) {
-                               tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
-                               tun_setup.type = dev->tuner_type;
-                               tun_setup.addr = ADDR_UNSET;
+                       tun_setup.mode_mask = T_RADIO     |
+                                             T_ANALOG_TV |
+                                             T_DIGITAL_TV;
+                       tun_setup.type = dev->tuner_type;
+                       tun_setup.addr = ADDR_UNSET;
+                       tun_setup.tuner_callback = saa7134_tuner_callback;
 
-                               saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+                       saa7134_i2c_call_clients(dev,
+                                                TUNER_SET_TYPE_ADDR,
+                                                &tun_setup);
                }
                break;
        case SAA7134_BOARD_MD7134:
@@ -5275,14 +5681,25 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                                                 &tda9887_cfg);
                }
 
-               tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+               tun_setup.mode_mask = T_RADIO     |
+                                     T_ANALOG_TV |
+                                     T_DIGITAL_TV;
                tun_setup.type = dev->tuner_type;
                tun_setup.addr = ADDR_UNSET;
 
-               saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+               saa7134_i2c_call_clients(dev,
+                                        TUNER_SET_TYPE_ADDR, &tun_setup);
                }
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
+               if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
+                       /* Reconfigure board as Snake reference design */
+                       dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
+                       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
+                               dev->name, saa7134_boards[dev->board].name);
+                       break;
+               }
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
                /* The Philips EUROPA based hybrid boards have the tuner connected through
@@ -5333,6 +5750,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
        case SAA7134_BOARD_AVERMEDIA_SUPER_007:
        case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+       case SAA7134_BOARD_CREATIX_CTX953:
                /* this is a hybrid board, initialize to analog mode
                 * and configure firmware eeprom address
                 */
@@ -5402,13 +5820,46 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                        break;
                }
                break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               {
+               struct v4l2_priv_tun_config tea5767_cfg;
+               struct tea5767_ctrl ctl;
+
+               dev->i2c_client.addr = 0xC0;
+               /* set TEA5767(analog FM) defines */
+               memset(&ctl, 0, sizeof(ctl));
+               ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+               tea5767_cfg.tuner = TUNER_TEA5767;
+               tea5767_cfg.priv  = &ctl;
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
+               }
+               break;
        }
+
+       if (dev->tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(ctl));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+               ctl.max_len = 64;
+
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+                       ctl.demod = XC3028_FE_ZARLINK456;
+                       break;
+               default:
+                       ctl.demod = XC3028_FE_OREN538;
+                       ctl.mts = 1;
+               }
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
+
        return 0;
 }
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 58ab163fdbd74e628e60655ea05c5d3bea611599..eec127864fe3e710832a34275c337b51819cf53b 100644 (file)
@@ -42,23 +42,23 @@ MODULE_LICENSE("GPL");
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug, int, 0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug, int, 0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int gpio_tracking = 0;
+static unsigned int gpio_tracking;
 module_param(gpio_tracking, int, 0644);
 MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
 
-static unsigned int alsa = 0;
+static unsigned int alsa;
 module_param(alsa, int, 0644);
 MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
 
-static unsigned int oss = 0;
+static unsigned int oss;
 module_param(oss, int, 0644);
 MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
 
@@ -142,39 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
        }
 }
 
-int saa7134_tuner_callback(void *ptr, int command, int arg)
-{
-       u8 sync_control;
-       struct saa7134_dev *dev = ptr;
-
-       switch (dev->tuner_type) {
-       case TUNER_PHILIPS_TDA8290:
-               switch (command) {
-               case 0: /* switch LNA gain through GPIO 22*/
-                       saa7134_set_gpio(dev, 22, arg) ;
-                       break;
-               case 1: /* vsync output at GPIO22. 50 / 60Hz */
-                       dprintk("setting GPIO22 to vsync %d\n", arg);
-                       saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
-                       saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
-                       if (arg == 1)
-                               sync_control = 11;
-                       else
-                               sync_control = 17;
-                       saa_writeb(SAA7134_VGATE_START, sync_control);
-                       saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
-                       saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       default:
-               return -ENODEV;
-       }
-       return 0;
-}
-
 /* ------------------------------------------------------------------ */
 
 
@@ -897,6 +864,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        struct saa7134_dev *dev;
        struct saa7134_mpeg_ops *mops;
        int err;
+       int mask;
+
+       if (saa7134_devcount == SAA7134_MAXBOARDS)
+               return -ENOMEM;
 
        dev = kzalloc(sizeof(*dev),GFP_KERNEL);
        if (NULL == dev)
@@ -1094,6 +1065,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
        if (TUNER_ABSENT != dev->tuner_type)
                saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
 
+       if (card(dev).gpiomask != 0) {
+               mask = card(dev).gpiomask;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0);
+       }
        return 0;
 
  fail4:
index ea2be9eceeb8bf90ad36ae2334a5c3b6e2cd2084..2d16be2259dbb6182b10d84b54585bfc66e81ed5 100644 (file)
 #include "saa7134.h"
 #include <media/v4l2-common.h>
 #include "dvb-pll.h"
+#include <dvb_frontend.h>
 
 #include "mt352.h"
 #include "mt352_priv.h" /* FIXME */
 #include "tda1004x.h"
 #include "nxt200x.h"
+#include "tuner-xc2028.h"
 
 #include "tda10086.h"
 #include "tda826x.h"
 #include "tda827x.h"
 #include "isl6421.h"
+#include "isl6405.h"
+#include "lnbp21.h"
+#include "tuner-simple.h"
 
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int antenna_pwr = 0;
+static unsigned int antenna_pwr;
 
 module_param(antenna_pwr, int, 0444);
 MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
 
-static int use_frontend = 0;
+static int use_frontend;
 module_param(use_frontend, int, 0644);
 MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define dprintk(fmt, arg...)   do { if (debug) \
        printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
 
@@ -91,7 +98,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
        saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
        udelay(10);
        ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
-       dprintk("%s %s\n", __FUNCTION__, ok ? "on" : "off");
+       dprintk("%s %s\n", __func__, ok ? "on" : "off");
 
        if (!ok)
                saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
@@ -111,7 +118,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
        static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
        struct saa7134_dev *dev= fe->dvb->priv;
 
-       dprintk("%s called\n", __FUNCTION__);
+       dprintk("%s called\n", __func__);
 
        mt352_write(fe, clock_config,   sizeof(clock_config));
        udelay(200);
@@ -146,6 +153,26 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
        return 0;
 }
 
+static int mt352_aver_a16d_init(struct dvb_frontend *fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x2d };
+       static u8 reset []         = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0xa0 };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+
+
 static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
                                           struct dvb_frontend_parameters* params)
 {
@@ -188,6 +215,16 @@ static struct mt352_config avermedia_777 = {
        .demod_init    = mt352_aver777_init,
 };
 
+static struct mt352_config avermedia_16d = {
+       .demod_address = 0xf,
+       .demod_init    = mt352_aver_a16d_init,
+};
+
+static struct mt352_config avermedia_e506r_mt352_dev = {
+       .demod_address   = (0x1e >> 1),
+       .no_tuner        = 1,
+};
+
 /* ==================================================================
  * tda1004x based DVB-T cards, helper functions
  */
@@ -430,8 +467,6 @@ static struct tda1004x_config philips_europa_config = {
        .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
 static struct tda1004x_config medion_cardbus = {
        .demod_address = 0x08,
        .invert        = 1,
@@ -447,47 +482,6 @@ static struct tda1004x_config medion_cardbus = {
  * tda 1004x based cards with philips silicon tuner
  */
 
-static void philips_tda827x_lna_gain(struct dvb_frontend *fe, int high)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->i2c_gate;
-       u8 config = state->config->tuner_config;
-       u8 GP00_CF[] = {0x20, 0x01};
-       u8 GP00_LEV[] = {0x22, 0x00};
-
-       struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = GP00_CF, .len = 2};
-       if (config) {
-               if (high) {
-                       dprintk("setting LNA to high gain\n");
-               } else {
-                       dprintk("setting LNA to low gain\n");
-               }
-       }
-       switch (config) {
-       case 0: /* no LNA */
-               break;
-       case 1: /* switch is GPIO 0 of tda8290 */
-       case 2:
-               /* turn Vsync off */
-               saa7134_set_gpio(dev, 22, 0);
-               GP00_LEV[1] = high ? 0 : 1;
-               if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
-                       wprintk("could not access tda8290 at addr: 0x%02x\n",
-                               addr << 1);
-                       return;
-               }
-               msg.buf = GP00_LEV;
-               if (config == 2)
-                       GP00_LEV[1] = high ? 1 : 0;
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       case 3: /* switch with GPIO of saa713x */
-               saa7134_set_gpio(dev, 22, high);
-               break;
-       }
-}
-
 static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
 {
        struct tda1004x_state *state = fe->demodulator_priv;
@@ -510,8 +504,6 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
        return 0;
 }
 
-/* ------------------------------------------------------------------ */
-
 static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -546,28 +538,57 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
        return 0;
 }
 
-static struct tda827x_config tda827x_cfg = {
-       .lna_gain = philips_tda827x_lna_gain,
-       .init = philips_tda827x_tuner_init,
-       .sleep = philips_tda827x_tuner_sleep
-};
-
-static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf)
+static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf,
+                                                         struct tda827x_config *tuner_conf)
 {
-       dev->dvb.frontend = dvb_attach(tda10046_attach, tda_conf, &dev->i2c_adap);
+       dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
        if (dev->dvb.frontend) {
-               if (tda_conf->i2c_gate)
+               if (cdec_conf->i2c_gate)
                        dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-               if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address,
-                                               &dev->i2c_adap,&tda827x_cfg) == NULL) {
+               if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address,
+                                                       &dev->i2c_adap, tuner_conf) == NULL) {
                        wprintk("no tda827x tuner found at addr: %02x\n",
-                               tda_conf->tuner_address);
+                               cdec_conf->tuner_address);
                }
        }
 }
 
 /* ------------------------------------------------------------------ */
 
+static struct tda827x_config tda827x_cfg_0 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 0,
+       .switch_addr = 0
+};
+
+static struct tda827x_config tda827x_cfg_1 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 1,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2_sw42 = {
+       .tuner_callback = saa7134_tuner_callback,
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x42
+};
+
+/* ------------------------------------------------------------------ */
+
 static struct tda1004x_config tda827x_lifeview_config = {
        .demod_address = 0x08,
        .invert        = 1,
@@ -590,7 +611,6 @@ static struct tda1004x_config philips_tiger_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -605,7 +625,6 @@ static struct tda1004x_config cinergy_ht_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -619,7 +638,6 @@ static struct tda1004x_config cinergy_ht_pci_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -633,7 +651,6 @@ static struct tda1004x_config philips_tiger_s_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -648,7 +665,6 @@ static struct tda1004x_config pinnacle_pctv_310i_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -662,7 +678,6 @@ static struct tda1004x_config hauppauge_hvr_1110_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -676,7 +691,6 @@ static struct tda1004x_config asus_p7131_dual_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 0,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -715,7 +729,6 @@ static struct tda1004x_config md8800_dvbt_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .request_firmware = philips_tda1004x_request_firmware
 };
 
@@ -729,7 +742,6 @@ static struct tda1004x_config asus_p7131_4871_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -744,7 +756,6 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 2,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -759,7 +770,6 @@ static struct tda1004x_config kworld_dvb_t_210_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -774,7 +784,6 @@ static struct tda1004x_config avermedia_super_007_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x4b,
        .tuner_address = 0x60,
-       .tuner_config  = 0,
        .antenna_switch= 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -789,7 +798,6 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
        .if_freq       = TDA10046_FREQ_045,
        .i2c_gate      = 0x42,
        .tuner_address = 0x61,
-       .tuner_config  = 2,
        .antenna_switch = 1,
        .request_firmware = philips_tda1004x_request_firmware
 };
@@ -817,9 +825,10 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 }
 
 static struct tda827x_config ads_duo_cfg = {
-       .lna_gain = philips_tda827x_lna_gain,
+       .tuner_callback = saa7134_tuner_callback,
        .init = ads_duo_tuner_init,
-       .sleep = ads_duo_tuner_sleep
+       .sleep = ads_duo_tuner_sleep,
+       .config = 0
 };
 
 static struct tda1004x_config ads_tech_duo_config = {
@@ -842,8 +851,73 @@ static struct tda10086_config flydvbs = {
        .demod_address = 0x0e,
        .invert = 0,
        .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
+static struct tda10086_config sd1878_4m = {
+       .demod_address = 0x0e,
+       .invert = 0,
+       .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_4M,
+};
+
+/* ------------------------------------------------------------------
+ * special case: lnb supply is connected to the gated i2c
+ */
+
+static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       int res = -EIO;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_voltage)
+                       res = dev->original_set_voltage(fe, voltage);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
+
+static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
+{
+       int res = -EIO;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_high_voltage)
+                       res = dev->original_set_high_voltage(fe, arg);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
+
+static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       u8 wbuf[2] = { 0x1f, 00 };
+       u8 rbuf;
+       struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 },
+                                { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } };
+
+       if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2)
+               return -EIO;
+       /* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */
+       if (voltage == SEC_VOLTAGE_18)
+               wbuf[1] = rbuf | 0x10;
+       else
+               wbuf[1] = rbuf & 0xef;
+       msg[0].len = 2;
+       i2c_transfer(&dev->i2c_adap, msg, 1);
+       return 0;
+}
+
+static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
+       return -EIO;
+}
+
 /* ==================================================================
  * nxt200x based ATSC cards, helper functions
  */
@@ -863,12 +937,14 @@ static struct nxt200x_config kworldatsc110 = {
 static int dvb_init(struct saa7134_dev *dev)
 {
        int ret;
+       int attach_xc3028 = 0;
+
        /* init struct videobuf_dvb */
        dev->ts.nr_bufs    = 32;
        dev->ts.nr_packets = 32*4;
        dev->dvb.name = dev->name;
-       videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_ALTERNATE,
                            sizeof(struct saa7134_buf),
@@ -889,17 +965,25 @@ static int dvb_init(struct saa7134_dev *dev)
                dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_PHILIPS_TD1316);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TD1316);
                }
                break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               dprintk("avertv A16D dvb setup\n");
+               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d,
+                                              &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
        case SAA7134_BOARD_MD7134:
                dev->dvb.frontend = dvb_attach(tda10046_attach,
                                               &medion_cardbus,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
-                                  &dev->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
@@ -913,7 +997,7 @@ static int dvb_init(struct saa7134_dev *dev)
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               configure_tda827x_fe(dev, &tda827x_lifeview_config);
+               configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
@@ -938,36 +1022,36 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_KWORLD_DVBT_210:
-               configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
+               configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
-               configure_tda827x_fe(dev, &philips_tiger_config);
+               configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
-               configure_tda827x_fe(dev, &pinnacle_pctv_310i_config);
+               configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1);
                break;
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               configure_tda827x_fe(dev, &hauppauge_hvr_1110_config);
+               configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1);
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               configure_tda827x_fe(dev, &asus_p7131_dual_config);
+               configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
-               configure_tda827x_fe(dev, &tda827x_lifeview_config);
+               configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
                if(! use_frontend) {    /* terrestrial */
-                       configure_tda827x_fe(dev, &lifeview_trio_config);
-               } else {                /* satellite */
+                       configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0);
+               } else {                /* satellite */
                        dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
                        if (dev->dvb.frontend) {
                                if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
                                                                        &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
+                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
                                }
                                if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
                                                                                0x08, 0, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
+                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
                                }
                        }
                }
@@ -979,18 +1063,56 @@ static int dvb_init(struct saa7134_dev *dev)
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        if (dvb_attach(tda827x_attach,dev->dvb.frontend,
-                                  ads_tech_duo_config.tuner_address,
-                                  &dev->i2c_adap,&ads_duo_cfg) == NULL) {
+                                  ads_tech_duo_config.tuner_address, &dev->i2c_adap,
+                                                               &ads_duo_cfg) == NULL) {
                                wprintk("no tda827x tuner found at addr: %02x\n",
                                        ads_tech_duo_config.tuner_address);
                        }
                }
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
-               configure_tda827x_fe(dev, &tevion_dvbt220rf_config);
+               configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
-               configure_tda827x_fe(dev, &md8800_dvbt_config);
+               if (!use_frontend) {     /* terrestrial */
+                       configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+               } else {        /* satellite */
+                       dev->dvb.frontend = dvb_attach(tda10086_attach,
+                                                       &flydvbs, &dev->i2c_adap);
+                       if (dev->dvb.frontend) {
+                               struct dvb_frontend *fe = dev->dvb.frontend;
+                               u8 dev_id = dev->eedata[2];
+                               u8 data = 0xc4;
+                               struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
+
+                               if (dvb_attach(tda826x_attach, dev->dvb.frontend,
+                                               0x60, &dev->i2c_adap, 0) == NULL)
+                                       wprintk("%s: Medion Quadro, no tda826x "
+                                               "found !\n", __func__);
+                               if (dev_id != 0x08) {
+                                       /* we need to open the i2c gate (we know it exists) */
+                                       fe->ops.i2c_gate_ctrl(fe, 1);
+                                       if (dvb_attach(isl6405_attach, fe,
+                                                       &dev->i2c_adap, 0x08, 0, 0) == NULL)
+                                               wprintk("%s: Medion Quadro, no ISL6405 "
+                                                       "found !\n", __func__);
+                                       if (dev_id == 0x07) {
+                                               /* fire up the 2nd section of the LNB supply since
+                                                  we can't do this from the other section */
+                                               msg.buf = &data;
+                                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                                       }
+                                       fe->ops.i2c_gate_ctrl(fe, 0);
+                                       dev->original_set_voltage = fe->ops.set_voltage;
+                                       fe->ops.set_voltage = md8800_set_voltage;
+                                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+                               } else {
+                                       fe->ops.set_voltage = md8800_set_voltage2;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2;
+                               }
+                       }
+               }
                break;
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
                dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
@@ -1004,8 +1126,9 @@ static int dvb_init(struct saa7134_dev *dev)
                dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
                                               &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_TUV1236D);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
                }
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
@@ -1014,11 +1137,11 @@ static int dvb_init(struct saa7134_dev *dev)
                if (dev->dvb.frontend) {
                        if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
                                       &dev->i2c_adap, 0) == NULL) {
-                               wprintk("%s: No tda826x found!\n", __FUNCTION__);
+                               wprintk("%s: No tda826x found!\n", __func__);
                        }
                        if (dvb_attach(isl6421_attach, dev->dvb.frontend,
                                       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
-                               wprintk("%s: No ISL6421 found!\n", __FUNCTION__);
+                               wprintk("%s: No ISL6421 found!\n", __func__);
                        }
                }
                break;
@@ -1030,8 +1153,9 @@ static int dvb_init(struct saa7134_dev *dev)
                        dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
                        dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
 
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
-                                  &dev->i2c_adap, DVB_PLL_FMD1216ME);
+                       dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
@@ -1044,38 +1168,107 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_CINERGY_HT_PCMCIA:
-               configure_tda827x_fe(dev, &cinergy_ht_config);
+               configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_CINERGY_HT_PCI:
-               configure_tda827x_fe(dev, &cinergy_ht_pci_config);
+               configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_PHILIPS_TIGER_S:
-               configure_tda827x_fe(dev, &philips_tiger_s_config);
+               configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_ASUS_P7131_4871:
-               configure_tda827x_fe(dev, &asus_p7131_4871_config);
+               configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-               configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config);
+               configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2);
                break;
        case SAA7134_BOARD_AVERMEDIA_SUPER_007:
-               configure_tda827x_fe(dev, &avermedia_super_007_config);
+               configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0);
                break;
        case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
-               configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config);
+               configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42);
+               break;
+       case SAA7134_BOARD_PHILIPS_SNAKE:
+               dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                               &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+                                       &dev->i2c_adap, 0) == NULL)
+                               wprintk("%s: No tda826x found!\n", __func__);
+                       if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+                                       &dev->i2c_adap, 0, 0) == NULL)
+                               wprintk("%s: No lnbp21 found!\n", __func__);
+               }
+               break;
+       case SAA7134_BOARD_CREATIX_CTX953:
+               configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+               break;
+       case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
+               configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &avermedia_e506r_mt352_dev,
+                                              &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_MD7134_BRIDGE_2:
+               dev->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &sd1878_4m, &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       struct dvb_frontend *fe;
+                       if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                 &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL)
+                               wprintk("%s: MD7134 DVB-S, no SD1878 "
+                                       "found !\n", __func__);
+                       /* we need to open the i2c gate (we know it exists) */
+                       fe = dev->dvb.frontend;
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+                       if (dvb_attach(isl6405_attach, fe,
+                                       &dev->i2c_adap, 0x08, 0, 0) == NULL)
+                               wprintk("%s: MD7134 DVB-S, no ISL6405 "
+                                       "found !\n", __func__);
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+                       dev->original_set_voltage = fe->ops.set_voltage;
+                       fe->ops.set_voltage = md8800_set_voltage;
+                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+               }
                break;
        default:
                wprintk("Huh? unknown DVB card?\n");
                break;
        }
 
+       if (attach_xc3028) {
+               struct dvb_frontend *fe;
+               struct xc2028_config cfg = {
+                       .i2c_adap  = &dev->i2c_adap,
+                       .i2c_addr  = 0x61,
+               };
+
+               if (!dev->dvb.frontend)
+                       return -1;
+
+               fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+               if (!fe) {
+                       printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                              dev->name);
+                       dvb_frontend_detach(dev->dvb.frontend);
+                       dvb_unregister_frontend(dev->dvb.frontend);
+                       dev->dvb.frontend = NULL;
+                       return -1;
+               }
+       }
+
        if (NULL == dev->dvb.frontend) {
                printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
                return -1;
        }
 
        /* register everything else */
-       ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+       ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
+                                   adapter_nr);
 
        /* this sequence is necessary to make the tda1004x load its firmware
         * and to enter analog mode of hybrid boards
@@ -1106,9 +1299,22 @@ static int dvb_fini(struct saa7134_dev *dev)
 
                /* otherwise we don't detect the tuner on next insmod */
                saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg);
+       } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
+               if ((dev->eedata[2] == 0x07) && use_frontend) {
+                       /* turn off the 2nd lnb supply */
+                       u8 data = 0x80;
+                       struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
+                       struct dvb_frontend *fe;
+                       fe = dev->dvb.frontend;
+                       if (fe->ops.i2c_gate_ctrl) {
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+                       }
+               }
        }
-
-       videobuf_dvb_unregister(&dev->dvb);
+       if (dev->dvb.frontend)
+               videobuf_dvb_unregister(&dev->dvb);
        return 0;
 }
 
index 3d2ec30de22799fc129bc80be208ef1c05c30146..1314522a8130784432147a5f8ad8e3ef35743a6f 100644 (file)
@@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
 module_param_array(empress_nr, int, NULL, 0444);
 MODULE_PARM_DESC(empress_nr,"ts device number");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages");
 
@@ -402,7 +402,7 @@ static int empress_init(struct saa7134_dev *dev)
 {
        int err;
 
-       dprintk("%s: %s\n",dev->name,__FUNCTION__);
+       dprintk("%s: %s\n",dev->name,__func__);
        dev->empress_dev = video_device_alloc();
        if (NULL == dev->empress_dev)
                return -ENOMEM;
@@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev)
        printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
               dev->name,dev->empress_dev->minor & 0x1f);
 
-       videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_ALTERNATE,
                            sizeof(struct saa7134_buf),
@@ -440,7 +440,7 @@ static int empress_init(struct saa7134_dev *dev)
 
 static int empress_fini(struct saa7134_dev *dev)
 {
-       dprintk("%s: %s\n",dev->name,__FUNCTION__);
+       dprintk("%s: %s\n",dev->name,__func__);
 
        if (NULL == dev->empress_dev)
                return 0;
index d3322c3018f2d6a7887584926005c025778f5b3d..2ccfaba0c490bfc6d42da43722a8ab6f665d42c9 100644 (file)
 
 /* ----------------------------------------------------------- */
 
-static unsigned int i2c_debug = 0;
+static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
 
-static unsigned int i2c_scan = 0;
+static unsigned int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
@@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status)
 {
        switch (status) {
        case BUSY:
+       case TO_SCL:
+       case TO_ARB:
                return true;
        default:
                return false;
index b4188819782f2c6a0ae180565ede8b87765f8292..767ff30832f27d9e613ca3883c9f174438a59064 100644 (file)
 #include "saa7134-reg.h"
 #include "saa7134.h"
 
-static unsigned int disable_ir = 0;
+static unsigned int disable_ir;
 module_param(disable_ir, int, 0444);
 MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
 
-static unsigned int ir_debug = 0;
+static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
 
-static int pinnacle_remote = 0;
+static int pinnacle_remote;
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
@@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                break;
        case SAA7134_BOARD_MANLI_MTV001:
        case SAA7134_BOARD_MANLI_MTV002:
+               ir_codes     = ir_codes_manli;
+               mask_keycode = 0x001f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; /* ms */
+               break;
        case SAA7134_BOARD_BEHOLD_409FM:
        case SAA7134_BOARD_BEHOLD_401:
        case SAA7134_BOARD_BEHOLD_403:
@@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_BEHOLD_505FM:
        case SAA7134_BOARD_BEHOLD_507_9FM:
                ir_codes     = ir_codes_manli;
-               mask_keycode = 0x001f00;
+               mask_keycode = 0x003f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; /* ms */
+               break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               ir_codes     = ir_codes_behold_columbus;
+               mask_keycode = 0x003f00;
                mask_keyup   = 0x004000;
                polling      = 50; // ms
                break;
index ac6431ba4fc37e9467b1c43b3ebb76582ff424f1..86f5eefdb0f6d94f5f245e4ded082688e91f975c 100644 (file)
 #define SAA7135_DSP_RWSTATE_RDB                 (1 << 1)
 #define SAA7135_DSP_RWSTATE_WRR                 (1 << 0)
 
+#define SAA7135_DSP_RWCLEAR                    0x586
+#define SAA7135_DSP_RWCLEAR_RERR                   1
+
 /* ------------------------------------------------------------------ */
 /*
  * Local variables:
index f1b8fcaeb43acc6ecddf2ae62c25aefafb117a76..eae72fd60cec6f6b3aa888d4bb380cb62cc10209 100644 (file)
@@ -32,7 +32,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int ts_debug  = 0;
+static unsigned int ts_debug;
 module_param(ts_debug, int, 0644);
 MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
 
index 4e9810469ae309c0ac41917c2764a7977301658e..232af598d94709a9d66ef0bd898f13efca3cffeb 100644 (file)
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int audio_debug = 0;
+static unsigned int audio_debug;
 module_param(audio_debug, int, 0644);
 MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
 
-static unsigned int audio_ddep = 0;
+static unsigned int audio_ddep;
 module_param(audio_ddep, int, 0644);
 MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite");
 
 static int audio_clock_override = UNSET;
 module_param(audio_clock_override, int, 0644);
 
-static int audio_clock_tweak = 0;
+static int audio_clock_tweak;
 module_param(audio_clock_tweak, int, 0644);
 MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
 
@@ -653,6 +653,17 @@ static char *stdres[0x20] = {
 
 #define DSP_RETRY 32
 #define DSP_DELAY 16
+#define SAA7135_DSP_RWCLEAR_RERR 1
+
+static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev)
+{
+       int state = saa_readb(SAA7135_DSP_RWSTATE);
+       if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+               d2printk("%s: resetting error bit\n", dev->name);
+               saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR);
+       }
+       return 0;
+}
 
 static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
 {
@@ -660,8 +671,8 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
 
        state = saa_readb(SAA7135_DSP_RWSTATE);
        if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
-               printk("%s: dsp access error\n",dev->name);
-               /* FIXME: send ack ... */
+               printk(KERN_WARNING "%s: dsp access error\n", dev->name);
+               saa_dsp_reset_error_bit(dev);
                return -EIO;
        }
        while (0 == (state & bit)) {
index f0d5ed9c2b0666e1152611f3325f89a6d8914182..cb0304298a96ec27419ba219259012ab021037b4 100644 (file)
@@ -31,7 +31,7 @@
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int vbi_debug  = 0;
+static unsigned int vbi_debug;
 module_param(vbi_debug, int, 0644);
 MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
 
index 39c41ad97d0ecfb3bafcec5fcc2a9ace517afe68..a0baf2d0ba7f307bade2c320716ce08b9b143d18 100644 (file)
@@ -40,7 +40,7 @@
 
 unsigned int video_debug;
 static unsigned int gbuffers      = 8;
-static unsigned int noninterlaced = 0;
+static unsigned int noninterlaced; /* 0 */
 static unsigned int gbufsize      = 720*576*4;
 static unsigned int gbufsize_max  = 720*576*4;
 static char secam[] = "--";
@@ -626,13 +626,8 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
 {
        saa7134_set_decoder(dev);
 
-       if (card_in(dev, dev->ctl_input).tv) {
-               if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
-                               && ((card(dev).tuner_config == 1)
-                               ||  (card(dev).tuner_config == 2)))
-                       saa7134_set_gpio(dev, 22, 5);
+       if (card_in(dev, dev->ctl_input).tv)
                saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
-       }
 }
 
 static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1350,14 +1345,14 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 576;
        v4l2_prio_open(&dev->prio,&fh->prio);
 
-       videobuf_queue_pci_init(&fh->cap, &video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->cap, &video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct saa7134_buf),
                            fh);
-       videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct saa7134_buf),
index f940d0254798a6eb6ae7da25e986be7998fa8bd6..924ffd13637ead8b5e66d058b037ae7b9cbb9bd1 100644 (file)
@@ -253,7 +253,17 @@ struct saa7134_format {
 #define SAA7134_BOARD_BEHOLD_607_9FM   129
 #define SAA7134_BOARD_BEHOLD_M6                130
 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
-#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
+#define SAA7134_BOARD_GENIUS_TVGO_A11MCE   132
+#define SAA7134_BOARD_PHILIPS_SNAKE        133
+#define SAA7134_BOARD_CREATIX_CTX953       134
+#define SAA7134_BOARD_MSI_TVANYWHERE_AD11  135
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136
+#define SAA7134_BOARD_AVERMEDIA_A16D       137
+#define SAA7134_BOARD_AVERMEDIA_M115       138
+#define SAA7134_BOARD_VIDEOMATE_T750       139
+#define SAA7134_BOARD_AVERMEDIA_A700_PRO    140
+#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
+
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -380,9 +390,7 @@ struct saa7134_fh {
        unsigned int               radio;
        enum v4l2_buf_type         type;
        unsigned int               resources;
-#ifdef VIDIOC_G_PRIORITY
        enum v4l2_priority         prio;
-#endif
 
        /* video overlay */
        struct v4l2_window         win;
@@ -454,9 +462,7 @@ struct saa7134_dev {
        struct list_head           devlist;
        struct mutex               lock;
        spinlock_t                 slock;
-#ifdef VIDIOC_G_PRIORITY
        struct v4l2_prio_state     prio;
-#endif
        /* workstruct for loading modules */
        struct work_struct request_module_wk;
 
@@ -556,7 +562,9 @@ struct saa7134_dev {
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
        /* SAA7134_MPEG_DVB only */
        struct videobuf_dvb        dvb;
-       int (*original_demod_sleep)(struct dvb_frontend* fe);
+       int (*original_demod_sleep)(struct dvb_frontend *fe);
+       int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+       int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
 #endif
 };
 
@@ -594,7 +602,6 @@ extern int saa7134_no_overlay;
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
-int saa7134_tuner_callback(void *ptr, int command, int arg);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -631,6 +638,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
 
 extern int saa7134_board_init1(struct saa7134_dev *dev);
 extern int saa7134_board_init2(struct saa7134_dev *dev);
+int saa7134_tuner_callback(void *priv, int command, int arg);
 
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
new file mode 100644 (file)
index 0000000..53c5edb
--- /dev/null
@@ -0,0 +1,1516 @@
+/*
+ * saa717x - Philips SAA717xHL video decoder driver
+ *
+ * Based on the saa7115 driver
+ *
+ * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
+ *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
+ *
+ * Changes by T.Adachi (tadachi@tadachi-net.com)
+ *    - support audio, video scaler etc, and checked the initialize sequence.
+ *
+ * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this is a reversed engineered driver based on captures from
+ * the I2C bus under Windows. This chip is very similar to the saa7134,
+ * though. Unfortunately, this driver is currently only working for NTSC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv.h>
+
+MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
+MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+struct saa717x_state {
+       v4l2_std_id std;
+       int input;
+       int enable;
+       int radio;
+       int bright;
+       int contrast;
+       int hue;
+       int sat;
+       int playback;
+       int audio;
+       int tuner_audio_mode;
+       int audio_main_mute;
+       int audio_main_vol_r;
+       int audio_main_vol_l;
+       u16 audio_main_bass;
+       u16 audio_main_treble;
+       u16 audio_main_volume;
+       u16 audio_main_balance;
+       int audio_input;
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* for audio mode */
+#define TUNER_AUDIO_MONO       0  /* LL */
+#define TUNER_AUDIO_STEREO     1  /* LR */
+#define TUNER_AUDIO_LANG1      2  /* LL */
+#define TUNER_AUDIO_LANG2      3  /* RR */
+
+#define SAA717X_NTSC_WIDTH     (704)
+#define SAA717X_NTSC_HEIGHT    (480)
+
+/* ----------------------------------------------------------------------- */
+
+static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
+{
+       struct i2c_adapter *adap = client->adapter;
+       int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
+       unsigned char mm1[6];
+       struct i2c_msg msg;
+
+       msg.flags = 0;
+       msg.addr = client->addr;
+       mm1[0] = (reg >> 8) & 0xff;
+       mm1[1] = reg & 0xff;
+
+       if (fw_addr) {
+               mm1[4] = (value >> 16) & 0xff;
+               mm1[3] = (value >> 8) & 0xff;
+               mm1[2] = value & 0xff;
+       } else {
+               mm1[2] = value & 0xff;
+       }
+       msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
+       msg.buf = mm1;
+       v4l_dbg(2, debug, client, "wrote:  reg 0x%03x=%08x\n", reg, value);
+       return i2c_transfer(adap, &msg, 1) == 1;
+}
+
+static void saa717x_write_regs(struct i2c_client *client, u32 *data)
+{
+       while (data[0] || data[1]) {
+               saa717x_write(client, data[0], data[1]);
+               data += 2;
+       }
+}
+
+static u32 saa717x_read(struct i2c_client *client, u32 reg)
+{
+       struct i2c_adapter *adap = client->adapter;
+       int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
+       unsigned char mm1[2];
+       unsigned char mm2[4] = { 0, 0, 0, 0 };
+       struct i2c_msg msgs[2];
+       u32 value;
+
+       msgs[0].flags = 0;
+       msgs[1].flags = I2C_M_RD;
+       msgs[0].addr = msgs[1].addr = client->addr;
+       mm1[0] = (reg >> 8) & 0xff;
+       mm1[1] = reg & 0xff;
+       msgs[0].len = 2;
+       msgs[0].buf = mm1;
+       msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
+       msgs[1].buf = mm2;
+       i2c_transfer(adap, msgs, 2);
+
+       if (fw_addr)
+               value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+       else
+               value = mm2[0] & 0xff;
+
+       v4l_dbg(2, debug, client, "read:  reg 0x%03x=0x%08x\n", reg, value);
+       return value;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static u32 reg_init_initialize[] =
+{
+       /* from linux driver */
+       0x101, 0x008, /* Increment delay */
+
+       0x103, 0x000, /* Analog input control 2 */
+       0x104, 0x090, /* Analog input control 3 */
+       0x105, 0x090, /* Analog input control 4 */
+       0x106, 0x0eb, /* Horizontal sync start */
+       0x107, 0x0e0, /* Horizontal sync stop */
+       0x109, 0x055, /* Luminance control */
+
+       0x10f, 0x02a, /* Chroma gain control */
+       0x110, 0x000, /* Chroma control 2 */
+
+       0x114, 0x045, /* analog/ADC */
+
+       0x118, 0x040, /* RAW data gain */
+       0x119, 0x080, /* RAW data offset */
+
+       0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
+       0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
+       0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
+       0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
+
+       0x049, 0x000, /* VBI vertical input window start (H) TASK A */
+
+       0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
+       0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
+
+       0x064, 0x080, /* Lumina brightness TASK A */
+       0x065, 0x040, /* Luminance contrast TASK A */
+       0x066, 0x040, /* Chroma saturation TASK A */
+       /* 067H: Reserved */
+       0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
+       0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
+       0x06a, 0x000, /* VBI phase offset TASK A */
+
+       0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
+       0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
+
+       0x072, 0x000, /* Vertical filter mode TASK A */
+
+       0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
+       0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
+       0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
+       0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
+
+       0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
+
+       0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
+       0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
+
+       0x0a4, 0x080, /* Lumina brightness TASK B */
+       0x0a5, 0x040, /* Luminance contrast TASK B */
+       0x0a6, 0x040, /* Chroma saturation TASK B */
+       /* 0A7H reserved */
+       0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
+       0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
+       0x0aa, 0x000, /* VBI phase offset TASK B */
+
+       0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
+       0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
+
+       0x0b2, 0x000, /* Vertical filter mode TASK B */
+
+       0x00c, 0x000, /* Start point GREEN path */
+       0x00d, 0x000, /* Start point BLUE path */
+       0x00e, 0x000, /* Start point RED path */
+
+       0x010, 0x010, /* GREEN path gamma curve --- */
+       0x011, 0x020,
+       0x012, 0x030,
+       0x013, 0x040,
+       0x014, 0x050,
+       0x015, 0x060,
+       0x016, 0x070,
+       0x017, 0x080,
+       0x018, 0x090,
+       0x019, 0x0a0,
+       0x01a, 0x0b0,
+       0x01b, 0x0c0,
+       0x01c, 0x0d0,
+       0x01d, 0x0e0,
+       0x01e, 0x0f0,
+       0x01f, 0x0ff, /* --- GREEN path gamma curve */
+
+       0x020, 0x010, /* BLUE path gamma curve --- */
+       0x021, 0x020,
+       0x022, 0x030,
+       0x023, 0x040,
+       0x024, 0x050,
+       0x025, 0x060,
+       0x026, 0x070,
+       0x027, 0x080,
+       0x028, 0x090,
+       0x029, 0x0a0,
+       0x02a, 0x0b0,
+       0x02b, 0x0c0,
+       0x02c, 0x0d0,
+       0x02d, 0x0e0,
+       0x02e, 0x0f0,
+       0x02f, 0x0ff, /* --- BLUE path gamma curve */
+
+       0x030, 0x010, /* RED path gamma curve --- */
+       0x031, 0x020,
+       0x032, 0x030,
+       0x033, 0x040,
+       0x034, 0x050,
+       0x035, 0x060,
+       0x036, 0x070,
+       0x037, 0x080,
+       0x038, 0x090,
+       0x039, 0x0a0,
+       0x03a, 0x0b0,
+       0x03b, 0x0c0,
+       0x03c, 0x0d0,
+       0x03d, 0x0e0,
+       0x03e, 0x0f0,
+       0x03f, 0x0ff, /* --- RED path gamma curve */
+
+       0x109, 0x085, /* Luminance control  */
+
+       /**** from app start ****/
+       0x584, 0x000, /* AGC gain control */
+       0x585, 0x000, /* Program count */
+       0x586, 0x003, /* Status reset */
+       0x588, 0x0ff, /* Number of audio samples (L) */
+       0x589, 0x00f, /* Number of audio samples (M) */
+       0x58a, 0x000, /* Number of audio samples (H) */
+       0x58b, 0x000, /* Audio select */
+       0x58c, 0x010, /* Audio channel assign1 */
+       0x58d, 0x032, /* Audio channel assign2 */
+       0x58e, 0x054, /* Audio channel assign3 */
+       0x58f, 0x023, /* Audio format */
+       0x590, 0x000, /* SIF control */
+
+       0x595, 0x000, /* ?? */
+       0x596, 0x000, /* ?? */
+       0x597, 0x000, /* ?? */
+
+       0x464, 0x00, /* Digital input crossbar1 */
+
+       0x46c, 0xbbbb10, /* Digital output selection1-3 */
+       0x470, 0x101010, /* Digital output selection4-6 */
+
+       0x478, 0x00, /* Sound feature control */
+
+       0x474, 0x18, /* Softmute control */
+
+       0x454, 0x0425b9, /* Sound Easy programming(reset) */
+       0x454, 0x042539, /* Sound Easy programming(reset) */
+
+
+       /**** common setting( of DVD play, including scaler commands) ****/
+       0x042, 0x003, /* Data path configuration for VBI (TASK A) */
+
+       0x082, 0x003, /* Data path configuration for VBI (TASK B) */
+
+       0x108, 0x0f8, /* Sync control */
+       0x2a9, 0x0fd, /* ??? */
+       0x102, 0x089, /* select video input "mode 9" */
+       0x111, 0x000, /* Mode/delay control */
+
+       0x10e, 0x00a, /* Chroma control 1 */
+
+       0x594, 0x002, /* SIF, analog I/O select */
+
+       0x454, 0x0425b9, /* Sound  */
+       0x454, 0x042539,
+
+       0x111, 0x000,
+       0x10e, 0x00a,
+       0x464, 0x000,
+       0x300, 0x000,
+       0x301, 0x006,
+       0x302, 0x000,
+       0x303, 0x006,
+       0x308, 0x040,
+       0x309, 0x000,
+       0x30a, 0x000,
+       0x30b, 0x000,
+       0x000, 0x002,
+       0x001, 0x000,
+       0x002, 0x000,
+       0x003, 0x000,
+       0x004, 0x033,
+       0x040, 0x01d,
+       0x041, 0x001,
+       0x042, 0x004,
+       0x043, 0x000,
+       0x080, 0x01e,
+       0x081, 0x001,
+       0x082, 0x004,
+       0x083, 0x000,
+       0x190, 0x018,
+       0x115, 0x000,
+       0x116, 0x012,
+       0x117, 0x018,
+       0x04a, 0x011,
+       0x08a, 0x011,
+       0x04b, 0x000,
+       0x08b, 0x000,
+       0x048, 0x000,
+       0x088, 0x000,
+       0x04e, 0x012,
+       0x08e, 0x012,
+       0x058, 0x012,
+       0x098, 0x012,
+       0x059, 0x000,
+       0x099, 0x000,
+       0x05a, 0x003,
+       0x09a, 0x003,
+       0x05b, 0x001,
+       0x09b, 0x001,
+       0x054, 0x008,
+       0x094, 0x008,
+       0x055, 0x000,
+       0x095, 0x000,
+       0x056, 0x0c7,
+       0x096, 0x0c7,
+       0x057, 0x002,
+       0x097, 0x002,
+       0x0ff, 0x0ff,
+       0x060, 0x001,
+       0x0a0, 0x001,
+       0x061, 0x000,
+       0x0a1, 0x000,
+       0x062, 0x000,
+       0x0a2, 0x000,
+       0x063, 0x000,
+       0x0a3, 0x000,
+       0x070, 0x000,
+       0x0b0, 0x000,
+       0x071, 0x004,
+       0x0b1, 0x004,
+       0x06c, 0x0e9,
+       0x0ac, 0x0e9,
+       0x06d, 0x003,
+       0x0ad, 0x003,
+       0x05c, 0x0d0,
+       0x09c, 0x0d0,
+       0x05d, 0x002,
+       0x09d, 0x002,
+       0x05e, 0x0f2,
+       0x09e, 0x0f2,
+       0x05f, 0x000,
+       0x09f, 0x000,
+       0x074, 0x000,
+       0x0b4, 0x000,
+       0x075, 0x000,
+       0x0b5, 0x000,
+       0x076, 0x000,
+       0x0b6, 0x000,
+       0x077, 0x000,
+       0x0b7, 0x000,
+       0x195, 0x008,
+       0x0ff, 0x0ff,
+       0x108, 0x0f8,
+       0x111, 0x000,
+       0x10e, 0x00a,
+       0x2a9, 0x0fd,
+       0x464, 0x001,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+
+
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x193, 0x000,
+       0x300, 0x000,
+       0x301, 0x006,
+       0x302, 0x000,
+       0x303, 0x006,
+       0x308, 0x040,
+       0x309, 0x000,
+       0x30a, 0x000,
+       0x30b, 0x000,
+       0x000, 0x002,
+       0x001, 0x000,
+       0x002, 0x000,
+       0x003, 0x000,
+       0x004, 0x033,
+       0x040, 0x01d,
+       0x041, 0x001,
+       0x042, 0x004,
+       0x043, 0x000,
+       0x080, 0x01e,
+       0x081, 0x001,
+       0x082, 0x004,
+       0x083, 0x000,
+       0x190, 0x018,
+       0x115, 0x000,
+       0x116, 0x012,
+       0x117, 0x018,
+       0x04a, 0x011,
+       0x08a, 0x011,
+       0x04b, 0x000,
+       0x08b, 0x000,
+       0x048, 0x000,
+       0x088, 0x000,
+       0x04e, 0x012,
+       0x08e, 0x012,
+       0x058, 0x012,
+       0x098, 0x012,
+       0x059, 0x000,
+       0x099, 0x000,
+       0x05a, 0x003,
+       0x09a, 0x003,
+       0x05b, 0x001,
+       0x09b, 0x001,
+       0x054, 0x008,
+       0x094, 0x008,
+       0x055, 0x000,
+       0x095, 0x000,
+       0x056, 0x0c7,
+       0x096, 0x0c7,
+       0x057, 0x002,
+       0x097, 0x002,
+       0x060, 0x001,
+       0x0a0, 0x001,
+       0x061, 0x000,
+       0x0a1, 0x000,
+       0x062, 0x000,
+       0x0a2, 0x000,
+       0x063, 0x000,
+       0x0a3, 0x000,
+       0x070, 0x000,
+       0x0b0, 0x000,
+       0x071, 0x004,
+       0x0b1, 0x004,
+       0x06c, 0x0e9,
+       0x0ac, 0x0e9,
+       0x06d, 0x003,
+       0x0ad, 0x003,
+       0x05c, 0x0d0,
+       0x09c, 0x0d0,
+       0x05d, 0x002,
+       0x09d, 0x002,
+       0x05e, 0x0f2,
+       0x09e, 0x0f2,
+       0x05f, 0x000,
+       0x09f, 0x000,
+       0x074, 0x000,
+       0x0b4, 0x000,
+       0x075, 0x000,
+       0x0b5, 0x000,
+       0x076, 0x000,
+       0x0b6, 0x000,
+       0x077, 0x000,
+       0x0b7, 0x000,
+       0x195, 0x008,
+       0x598, 0x0e7,
+       0x599, 0x07d,
+       0x59a, 0x018,
+       0x59c, 0x066,
+       0x59d, 0x090,
+       0x59e, 0x001,
+       0x584, 0x000,
+       0x585, 0x000,
+       0x586, 0x003,
+       0x588, 0x0ff,
+       0x589, 0x00f,
+       0x58a, 0x000,
+       0x58b, 0x000,
+       0x58c, 0x010,
+       0x58d, 0x032,
+       0x58e, 0x054,
+       0x58f, 0x023,
+       0x590, 0x000,
+       0x595, 0x000,
+       0x596, 0x000,
+       0x597, 0x000,
+       0x464, 0x000,
+       0x46c, 0xbbbb10,
+       0x470, 0x101010,
+       0x478, 0x000,
+       0x474, 0x018,
+       0x454, 0x042135,
+       0x193, 0x0a6,
+       0x108, 0x0f8,
+       0x042, 0x003,
+       0x082, 0x003,
+       0x454, 0x0425b9,
+       0x454, 0x042539,
+       0x193, 0x000,
+       0x193, 0x0a6,
+       0x464, 0x000,
+
+       0, 0
+};
+
+/* Tuner */
+static u32 reg_init_tuner_input[] = {
+       0x108, 0x0f8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x00a, /* Chroma control 1 */
+       0, 0
+};
+
+/* Composite */
+static u32 reg_init_composite_input[] = {
+       0x108, 0x0e8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x04a, /* Chroma control 1 */
+       0, 0
+};
+
+/* S-Video */
+static u32 reg_init_svideo_input[] = {
+       0x108, 0x0e8, /* Sync control */
+       0x111, 0x000, /* Mode/delay control */
+       0x10e, 0x04a, /* Chroma control 1 */
+       0, 0
+};
+
+static u32 reg_set_audio_template[4][2] =
+{
+       { /* for MONO
+               tadachi 6/29 DMA audio output select?
+               Register 0x46c
+               7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
+               0: MAIN left,  1: MAIN right
+               2: AUX1 left,  3: AUX1 right
+               4: AUX2 left,  5: AUX2 right
+               6: DPL left,   7: DPL  right
+               8: DPL center, 9: DPL surround
+               A: monitor output, B: digital sense */
+               0xbbbb00,
+
+               /* tadachi 6/29 DAC and I2S output select?
+                  Register 0x470
+                  7-4:DAC right ch. 3-0:DAC left ch.
+                  I2S1 right,left  I2S2 right,left */
+               0x00,
+       },
+       { /* for STEREO */
+               0xbbbb10, 0x101010,
+       },
+       { /* for LANG1 */
+               0xbbbb00, 0x00,
+       },
+       { /* for LANG2/SAP */
+               0xbbbb11, 0x111111,
+       }
+};
+
+
+/* Get detected audio flags (from saa7134 driver) */
+static void get_inf_dev_status(struct i2c_client *client,
+               int *dual_flag, int *stereo_flag)
+{
+       u32 reg_data3;
+
+       static char *stdres[0x20] = {
+               [0x00] = "no standard detected",
+               [0x01] = "B/G (in progress)",
+               [0x02] = "D/K (in progress)",
+               [0x03] = "M (in progress)",
+
+               [0x04] = "B/G A2",
+               [0x05] = "B/G NICAM",
+               [0x06] = "D/K A2 (1)",
+               [0x07] = "D/K A2 (2)",
+               [0x08] = "D/K A2 (3)",
+               [0x09] = "D/K NICAM",
+               [0x0a] = "L NICAM",
+               [0x0b] = "I NICAM",
+
+               [0x0c] = "M Korea",
+               [0x0d] = "M BTSC ",
+               [0x0e] = "M EIAJ",
+
+               [0x0f] = "FM radio / IF 10.7 / 50 deemp",
+               [0x10] = "FM radio / IF 10.7 / 75 deemp",
+               [0x11] = "FM radio / IF sel / 50 deemp",
+               [0x12] = "FM radio / IF sel / 75 deemp",
+
+               [0x13 ... 0x1e] = "unknown",
+               [0x1f] = "??? [in progress]",
+       };
+
+
+       *dual_flag = *stereo_flag = 0;
+
+       /* (demdec status: 0x528) */
+
+       /* read current status */
+       reg_data3 = saa717x_read(client, 0x0528);
+
+       v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
+               reg_data3, stdres[reg_data3 & 0x1f],
+               (reg_data3 & 0x000020) ? ",stereo" : "",
+               (reg_data3 & 0x000040) ? ",dual"   : "");
+       v4l_dbg(1, debug, client, "detailed status: "
+               "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+               (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
+               (reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
+               (reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
+               (reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
+
+               (reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
+               (reg_data3 & 0x001000) ? " SAP carrier "            : "",
+               (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
+               (reg_data3 & 0x004000) ? " SAP noise mute "         : "",
+               (reg_data3 & 0x008000) ? " VDSP "                   : "",
+
+               (reg_data3 & 0x010000) ? " NICST "                  : "",
+               (reg_data3 & 0x020000) ? " NICDU "                  : "",
+               (reg_data3 & 0x040000) ? " NICAM muted "            : "",
+               (reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
+
+               (reg_data3 & 0x100000) ? " init done "              : "");
+
+       if (reg_data3 & 0x000220) {
+               v4l_dbg(1, debug, client, "ST!!!\n");
+               *stereo_flag = 1;
+       }
+
+       if (reg_data3 & 0x000140) {
+               v4l_dbg(1, debug, client, "DUAL!!!\n");
+               *dual_flag = 1;
+       }
+}
+
+/* regs write to set audio mode */
+static void set_audio_mode(struct i2c_client *client, int audio_mode)
+{
+       v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
+                       audio_mode);
+
+       saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
+       saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
+}
+
+/* write regs to video output level (bright,contrast,hue,sat) */
+static void set_video_output_level_regs(struct i2c_client *client,
+               struct saa717x_state *decoder)
+{
+       /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
+       saa717x_write(client, 0x10a, decoder->bright);
+
+       /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
+          0h (luminance off) 40: i2c dump
+          c0h (-1.0 inverse chrominance)
+          80h (-2.0 inverse chrominance) */
+       saa717x_write(client, 0x10b, decoder->contrast);
+
+       /* saturation? 7fh(max)-40h(ITU)-0h(color off)
+          c0h (-1.0 inverse chrominance)
+          80h (-2.0 inverse chrominance) */
+       saa717x_write(client, 0x10c, decoder->sat);
+
+       /* color hue (phase) control
+          7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
+       saa717x_write(client, 0x10d, decoder->hue);
+}
+
+/* write regs to set audio volume, bass and treble */
+static int set_audio_regs(struct i2c_client *client,
+               struct saa717x_state *decoder)
+{
+       u8 mute = 0xac; /* -84 dB */
+       u32 val;
+       unsigned int work_l, work_r;
+
+       /* set SIF analog I/O select */
+       saa717x_write(client, 0x0594, decoder->audio_input);
+       v4l_dbg(1, debug, client, "set audio input %d\n",
+                       decoder->audio_input);
+
+       /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
+       work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
+       work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
+       decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
+       decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
+
+       /* set main volume */
+       /* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
+       /*    def:0dB->6dB(MPG600GR) */
+       /* if mute is on, set mute */
+       if (decoder->audio_main_mute) {
+               val = mute | (mute << 8);
+       } else {
+               val = (u8)decoder->audio_main_vol_l |
+                       ((u8)decoder->audio_main_vol_r << 8);
+       }
+
+       saa717x_write(client, 0x480, val);
+
+       /* bass and treble; go to another function */
+       /* set bass and treble */
+       val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
+       saa717x_write(client, 0x488, val);
+       return 0;
+}
+
+/********** scaling staff ***********/
+static void set_h_prescale(struct i2c_client *client,
+               int task, int prescale)
+{
+       static const struct {
+               int xpsc;
+               int xacl;
+               int xc2_1;
+               int xdcg;
+               int vpfy;
+       } vals[] = {
+               /* XPSC XACL XC2_1 XDCG VPFY */
+               {    1,   0,    0,    0,   0 },
+               {    2,   2,    1,    2,   2 },
+               {    3,   4,    1,    3,   2 },
+               {    4,   8,    1,    4,   2 },
+               {    5,   8,    1,    4,   2 },
+               {    6,   8,    1,    4,   3 },
+               {    7,   8,    1,    4,   3 },
+               {    8,  15,    0,    4,   3 },
+               {    9,  15,    0,    4,   3 },
+               {   10,  16,    1,    5,   3 },
+       };
+       static const int count = ARRAY_SIZE(vals);
+       int i, task_shift;
+
+       task_shift = task * 0x40;
+       for (i = 0; i < count; i++)
+               if (vals[i].xpsc == prescale)
+                       break;
+       if (i == count)
+               return;
+
+       /* horizonal prescaling */
+       saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
+       /* accumulation length */
+       saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
+       /* level control */
+       saa717x_write(client, 0x62 + task_shift,
+                       (vals[i].xc2_1 << 3) | vals[i].xdcg);
+       /*FIR prefilter control */
+       saa717x_write(client, 0x63 + task_shift,
+                       (vals[i].vpfy << 2) | vals[i].vpfy);
+}
+
+/********** scaling staff ***********/
+static void set_v_scale(struct i2c_client *client, int task, int yscale)
+{
+       int task_shift;
+
+       task_shift = task * 0x40;
+       /* Vertical scaling ratio (LOW) */
+       saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
+       /* Vertical scaling ratio (HI) */
+       saa717x_write(client, 0x71 + task_shift, yscale >> 8);
+}
+
+static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
+{
+       /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
+       return 0;
+}
+
+static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct saa717x_state *state = i2c_get_clientdata(client);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               if (ctrl->value < 0 || ctrl->value > 255) {
+                       v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->bright = ctrl->value;
+               v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
+               saa717x_write(client, 0x10a, state->bright);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->contrast = ctrl->value;
+               v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
+               saa717x_write(client, 0x10b, state->contrast);
+               break;
+
+       case V4L2_CID_SATURATION:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->sat = ctrl->value;
+               v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
+               saa717x_write(client, 0x10c, state->sat);
+               break;
+
+       case V4L2_CID_HUE:
+               if (ctrl->value < -127 || ctrl->value > 127) {
+                       v4l_err(client, "invalid hue setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               state->hue = ctrl->value;
+               v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
+               saa717x_write(client, 0x10d, state->hue);
+               break;
+
+       case V4L2_CID_AUDIO_MUTE:
+               state->audio_main_mute = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_VOLUME:
+               state->audio_main_volume = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_BALANCE:
+               state->audio_main_balance = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_TREBLE:
+               state->audio_main_treble = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       case V4L2_CID_AUDIO_BASS:
+               state->audio_main_bass = ctrl->value;
+               set_audio_regs(client, state);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+       struct saa717x_state *state = i2c_get_clientdata(client);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = state->bright;
+               break;
+
+       case V4L2_CID_CONTRAST:
+               ctrl->value = state->contrast;
+               break;
+
+       case V4L2_CID_SATURATION:
+               ctrl->value = state->sat;
+               break;
+
+       case V4L2_CID_HUE:
+               ctrl->value = state->hue;
+               break;
+
+       case V4L2_CID_AUDIO_MUTE:
+               ctrl->value = state->audio_main_mute;
+               break;
+
+       case V4L2_CID_AUDIO_VOLUME:
+               ctrl->value = state->audio_main_volume;
+               break;
+
+       case V4L2_CID_AUDIO_BALANCE:
+               ctrl->value = state->audio_main_balance;
+               break;
+
+       case V4L2_CID_AUDIO_TREBLE:
+               ctrl->value = state->audio_main_treble;
+               break;
+
+       case V4L2_CID_AUDIO_BASS:
+               ctrl->value = state->audio_main_bass;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct v4l2_queryctrl saa717x_qctrl[] = {
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 128,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_CONTRAST,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_SATURATION,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_HUE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 0,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 58880,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BALANCE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Balance",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .step          = 1,
+               .default_value = 1,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BASS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Bass",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+       }, {
+               .id            = V4L2_CID_AUDIO_TREBLE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Treble",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535 / 100,
+               .default_value = 32768,
+       },
+};
+
+static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
+{
+       int is_tuner = inp & 0x80;  /* tuner input flag */
+
+       inp &= 0x7f;
+
+       v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
+       /* inputs from 0-9 are available*/
+       /* saa717x have mode0-mode9 but mode5 is reserved. */
+       if (inp < 0 || inp > 9 || inp == 5)
+               return -EINVAL;
+
+       if (decoder->input != inp) {
+               int input_line = inp;
+
+               decoder->input = input_line;
+               v4l_dbg(1, debug, client,  "now setting %s input %d\n",
+                               input_line >= 6 ? "S-Video" : "Composite",
+                               input_line);
+
+               /* select mode */
+               saa717x_write(client, 0x102,
+                               (saa717x_read(client, 0x102) & 0xf0) |
+                               input_line);
+
+               /* bypass chrominance trap for modes 6..9 */
+               saa717x_write(client, 0x109,
+                               (saa717x_read(client, 0x109) & 0x7f) |
+                               (input_line < 6 ? 0x0 : 0x80));
+
+               /* change audio_mode */
+               if (is_tuner) {
+                       /* tuner */
+                       set_audio_mode(client, decoder->tuner_audio_mode);
+               } else {
+                       /* Force to STEREO mode if Composite or
+                        * S-Video were chosen */
+                       set_audio_mode(client, TUNER_AUDIO_STEREO);
+               }
+               /* change initialize procedure (Composite/S-Video) */
+               if (is_tuner)
+                       saa717x_write_regs(client, reg_init_tuner_input);
+               else if (input_line >= 6)
+                       saa717x_write_regs(client, reg_init_svideo_input);
+               else
+                       saa717x_write_regs(client, reg_init_composite_input);
+       }
+
+       return 0;
+}
+
+static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+       struct saa717x_state *decoder = i2c_get_clientdata(client);
+
+       v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
+
+       switch (cmd) {
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
+
+       case VIDIOC_G_CTRL:
+               return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
+
+       case VIDIOC_S_CTRL:
+               return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
+
+       case VIDIOC_QUERYCTRL: {
+               struct v4l2_queryctrl *qc = arg;
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
+                       if (qc->id && qc->id == saa717x_qctrl[i].id) {
+                               memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
+                               return 0;
+                       }
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       case VIDIOC_DBG_G_REGISTER: {
+               struct v4l2_register *reg = arg;
+
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               reg->val = saa717x_read(client, reg->reg);
+               break;
+       }
+
+       case VIDIOC_DBG_S_REGISTER: {
+               struct v4l2_register *reg = arg;
+               u16 addr = reg->reg & 0xffff;
+               u8 val = reg->val & 0xff;
+
+               if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               saa717x_write(client, addr, val);
+               break;
+       }
+#endif
+
+       case VIDIOC_S_FMT: {
+               struct v4l2_format *fmt = (struct v4l2_format *)arg;
+               struct v4l2_pix_format *pix;
+               int prescale, h_scale, v_scale;
+
+               pix = &fmt->fmt.pix;
+               v4l_dbg(1, debug, client, "decoder set size\n");
+
+               /* FIXME need better bounds checking here */
+               if (pix->width < 1 || pix->width > 1440)
+                       return -EINVAL;
+               if (pix->height < 1 || pix->height > 960)
+                       return -EINVAL;
+
+               /* scaling setting */
+               /* NTSC and interlace only */
+               prescale = SAA717X_NTSC_WIDTH / pix->width;
+               if (prescale == 0)
+                       prescale = 1;
+               h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
+               /* interlace */
+               v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
+
+               /* Horizontal prescaling etc */
+               set_h_prescale(client, 0, prescale);
+               set_h_prescale(client, 1, prescale);
+
+               /* Horizontal scaling increment */
+               /* TASK A */
+               saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
+               saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
+               saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
+
+               /* Vertical prescaling etc */
+               set_v_scale(client, 0, v_scale);
+               set_v_scale(client, 1, v_scale);
+
+               /* set video output size */
+               /* video number of pixels at output */
+               /* TASK A */
+               saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
+               saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
+               saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
+
+               /* video number of lines at output */
+               /* TASK A */
+               saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
+               saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
+               /* TASK B */
+               saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
+               saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
+               break;
+       }
+
+       case AUDC_SET_RADIO:
+               decoder->radio = 1;
+               break;
+
+       case VIDIOC_S_STD: {
+               v4l2_std_id std = *(v4l2_std_id *) arg;
+
+               v4l_dbg(1, debug, client, "decoder set norm ");
+               v4l_dbg(1, debug, client, "(not yet implementd)\n");
+
+               decoder->radio = 0;
+               decoder->std = std;
+               break;
+       }
+
+       case VIDIOC_INT_G_AUDIO_ROUTING: {
+               struct v4l2_routing *route = arg;
+
+               route->input = decoder->audio_input;
+               route->output = 0;
+               break;
+       }
+
+       case VIDIOC_INT_S_AUDIO_ROUTING: {
+               struct v4l2_routing *route = arg;
+
+               if (route->input < 3) { /* FIXME! --tadachi */
+                       decoder->audio_input = route->input;
+                       v4l_dbg(1, debug, client,
+                               "set decoder audio input to %d\n",
+                               decoder->audio_input);
+                       set_audio_regs(client, decoder);
+                       break;
+               }
+               return -ERANGE;
+       }
+
+       case VIDIOC_INT_S_VIDEO_ROUTING: {
+               struct v4l2_routing *route = arg;
+               int inp = route->input;
+
+               return saa717x_set_video_input(client, decoder, inp);
+       }
+
+       case VIDIOC_STREAMON: {
+               v4l_dbg(1, debug, client, "decoder enable output\n");
+               decoder->enable = 1;
+               saa717x_write(client, 0x193, 0xa6);
+               break;
+       }
+
+       case VIDIOC_STREAMOFF: {
+               v4l_dbg(1, debug, client, "decoder disable output\n");
+               decoder->enable = 0;
+               saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
+               break;
+       }
+
+               /* change audio mode */
+       case VIDIOC_S_TUNER: {
+               struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+               int audio_mode;
+               char *mes[4] = {
+                       "MONO", "STEREO", "LANG1", "LANG2/SAP"
+               };
+
+               audio_mode = V4L2_TUNER_MODE_STEREO;
+
+               switch (vt->audmode) {
+               case V4L2_TUNER_MODE_MONO:
+                       audio_mode = TUNER_AUDIO_MONO;
+                       break;
+               case V4L2_TUNER_MODE_STEREO:
+                       audio_mode = TUNER_AUDIO_STEREO;
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       audio_mode = TUNER_AUDIO_LANG2;
+                       break;
+               case V4L2_TUNER_MODE_LANG1:
+                       audio_mode = TUNER_AUDIO_LANG1;
+                       break;
+               }
+
+               v4l_dbg(1, debug, client, "change audio mode to %s\n",
+                               mes[audio_mode]);
+               decoder->tuner_audio_mode = audio_mode;
+               /* The registers are not changed here. */
+               /* See DECODER_ENABLE_OUTPUT section. */
+               set_audio_mode(client, decoder->tuner_audio_mode);
+               break;
+       }
+
+       case VIDIOC_G_TUNER: {
+               struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+               int dual_f, stereo_f;
+
+               if (decoder->radio)
+                       break;
+               get_inf_dev_status(client, &dual_f, &stereo_f);
+
+               v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
+                               stereo_f, dual_f);
+
+               /* mono */
+               if ((dual_f == 0) && (stereo_f == 0)) {
+                       vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+                       v4l_dbg(1, debug, client, "DETECT==MONO\n");
+               }
+
+               /* stereo */
+               if (stereo_f == 1) {
+                       if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
+                           vt->audmode == V4L2_TUNER_MODE_LANG1) {
+                               vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+                               v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
+                       } else {
+                               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
+                       }
+               }
+
+               /* dual */
+               if (dual_f == 1) {
+                       if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
+                               vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
+                       } else {
+                               vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
+                               v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
+                       }
+               }
+               break;
+       }
+
+       case VIDIOC_LOG_STATUS:
+               /* not yet implemented */
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+
+/* i2c implementation */
+
+/* ----------------------------------------------------------------------- */
+static int saa717x_probe(struct i2c_client *client)
+{
+       struct saa717x_state *decoder;
+       u8 id = 0;
+       char *p = "";
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+
+       snprintf(client->name, sizeof(client->name) - 1, "saa717x");
+
+       if (saa717x_write(client, 0x5a4, 0xfe) &&
+                       saa717x_write(client, 0x5a5, 0x0f) &&
+                       saa717x_write(client, 0x5a6, 0x00) &&
+                       saa717x_write(client, 0x5a7, 0x01))
+               id = saa717x_read(client, 0x5a0);
+       if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
+               v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
+               return -ENODEV;
+       }
+       if (id == 0xc2)
+               p = "saa7173";
+       else if (id == 0x32)
+               p = "saa7174A";
+       else if (id == 0x6c)
+               p = "saa7174HL";
+       else
+               p = "saa7171";
+       v4l_info(client, "%s found @ 0x%x (%s)\n", p,
+                       client->addr << 1, client->adapter->name);
+
+       decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
+       i2c_set_clientdata(client, decoder);
+
+       if (decoder == NULL)
+               return -ENOMEM;
+       decoder->std = V4L2_STD_NTSC;
+       decoder->input = -1;
+       decoder->enable = 1;
+
+       /* tune these parameters */
+       decoder->bright = 0x80;
+       decoder->contrast = 0x44;
+       decoder->sat = 0x40;
+       decoder->hue = 0x00;
+
+       /* FIXME!! */
+       decoder->playback = 0;  /* initially capture mode used */
+       decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
+
+       decoder->audio_input = 2; /* FIXME!! */
+
+       decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
+       /* set volume, bass and treble */
+       decoder->audio_main_vol_l = 6;
+       decoder->audio_main_vol_r = 6;
+       decoder->audio_main_bass = 0;
+       decoder->audio_main_treble = 0;
+       decoder->audio_main_mute = 0;
+       decoder->audio_main_balance = 32768;
+       /* normalize (24 to -40 (not -84) -> 65535 to 0) */
+       decoder->audio_main_volume =
+               (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
+
+       v4l_dbg(1, debug, client, "writing init values\n");
+
+       /* FIXME!! */
+       saa717x_write_regs(client, reg_init_initialize);
+       set_video_output_level_regs(client, decoder);
+       /* set bass,treble to 0db 20041101 K.Ohta */
+       decoder->audio_main_bass = 0;
+       decoder->audio_main_treble = 0;
+       set_audio_regs(client, decoder);
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(2*HZ);
+       return 0;
+}
+
+static int saa717x_remove(struct i2c_client *client)
+{
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "saa717x",
+       .driverid = I2C_DRIVERID_SAA717X,
+       .command = saa717x_command,
+       .probe = saa717x_probe,
+       .remove = saa717x_remove,
+       .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
+};
index 41f70440fd3bcb2b842720680d4d42a3b97476a9..02fda4eecea3269080eb14c5cd36d20d22df5803 100644 (file)
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index d5d7d6cf734aba40ca0c224051a206bd52fd1b4a..1cd629380f7183c94882fca69c1f4a4e85c67784 100644 (file)
@@ -35,7 +35,7 @@ static const char version[] = "0.24";
 #include <linux/usb.h>
 #include "se401.h"
 
-static int flickerless=0;
+static int flickerless;
 static int video_nr = -1;
 
 static struct usb_device_id device_table [] = {
@@ -300,10 +300,10 @@ static void se401_button_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -315,7 +315,7 @@ exit:
        status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __func__, status);
 }
 
 static void se401_video_irq(struct urb *urb)
@@ -1224,7 +1224,9 @@ static const struct file_operations se401_fops = {
        .read =         se401_read,
        .mmap =         se401_mmap,
        .ioctl =        se401_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device se401_template = {
@@ -1279,7 +1281,7 @@ static int se401_init(struct usb_se401 *se401, int button)
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
        se401->cheight=cp[0]+cp[1]*256;
 
-       if (!cp[2] && SE401_FORMAT_BAYER) {
+       if (!(cp[2] & SE401_FORMAT_BAYER)) {
                err("Bayer format not supported!");
                return 1;
        }
index 2e3c3de793a72a2161a2bf1c0ca69fd8c3b91b7c..0c8d87d8d18dd0b7e3b60b1b530942f944bfef96 100644 (file)
@@ -176,7 +176,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -191,7 +191,7 @@ do {                                                                          \
                        pr_info("sn9c102: " fmt "\n", ## args);               \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #else
@@ -202,7 +202,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index c40ba3adab21ccc24ff8ab27a3f6ffeef1bb04a1..5748b1e1a128aacdff1abfbdc756d1c6048963a3 100644 (file)
@@ -464,9 +464,9 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
 }
 
 
-int
-sn9c102_i2c_try_write(struct sn9c102_device* cam,
-                     const struct sn9c102_sensor* sensor, u8 address, u8 value)
+static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
+                                const struct sn9c102_sensor* sensor,
+                                u8 address, u8 value)
 {
        return sn9c102_i2c_try_raw_write(cam, sensor, 3,
                                         sensor->i2c_slave_id, address,
@@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
 
                /* Search for the SOF marker (fixed part) in the header */
                for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
-                       if (unlikely(i+j) == len)
+                       if (unlikely(i+j == len))
                                return NULL;
                        if (*(m+i+j) == marker[cam->sof.bytesread]) {
                                cam->sof.header[cam->sof.bytesread] = *(m+i+j);
@@ -3224,7 +3224,9 @@ static const struct file_operations sn9c102_fops = {
        .open = sn9c102_open,
        .release = sn9c102_release,
        .ioctl = sn9c102_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
@@ -3239,7 +3241,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct sn9c102_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0, r;
 
index 2dc7c68694840cb006cd99a39c60d54e989a8e51..4af7382da5c523d93ab61dcb57868ffbb7098daf 100644 (file)
@@ -85,9 +85,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
 */
 
 /* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_write(struct sn9c102_device*,
-                                const struct sn9c102_sensor*, u8 address,
-                                u8 value);
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,
                                const struct sn9c102_sensor*, u8 address);
 
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
new file mode 100644 (file)
index 0000000..a1b9244
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * camera image capture (abstract) bus driver
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This driver provides an interface between platform-specific camera
+ * busses and camera devices. It should be used if the camera is
+ * connected not over a "proper" bus like PCI or USB, but over a
+ * special bus, like, for example, the Quick Capture interface on PXA270
+ * SoCs. Later it should also be used for i.MX31 SoCs from Freescale.
+ * It can handle multiple cameras and / or multiple busses, which can
+ * be used, e.g., in stereo-vision applications.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/soc_camera.h>
+
+static LIST_HEAD(hosts);
+static LIST_HEAD(devices);
+static DEFINE_MUTEX(list_lock);
+static DEFINE_MUTEX(video_lock);
+
+const static struct soc_camera_data_format*
+format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < icd->num_formats; i++)
+               if (icd->formats[i].fourcc == fourcc)
+                       return icd->formats + i;
+       return NULL;
+}
+
+static int soc_camera_try_fmt_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       enum v4l2_field field;
+       const struct soc_camera_data_format *fmt;
+       int ret;
+
+       WARN_ON(priv != file->private_data);
+
+       fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
+       if (!fmt) {
+               dev_dbg(&icd->dev, "invalid format 0x%08x\n",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc);
+
+       field = f->fmt.pix.field;
+
+       if (field == V4L2_FIELD_ANY) {
+               field = V4L2_FIELD_NONE;
+       } else if (V4L2_FIELD_NONE != field) {
+               dev_err(&icd->dev, "Field type invalid.\n");
+               return -EINVAL;
+       }
+
+       /* test physical bus parameters */
+       ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat);
+       if (ret)
+               return ret;
+
+       /* limit format to hardware capabilities */
+       ret = ici->ops->try_fmt_cap(icd, f);
+
+       /* calculate missing fields */
+       f->fmt.pix.field = field;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return ret;
+}
+
+static int soc_camera_enum_input(struct file *file, void *priv,
+                                struct v4l2_input *inp)
+{
+       if (inp->index != 0)
+               return -EINVAL;
+
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = V4L2_STD_UNKNOWN;
+       strcpy(inp->name, "Camera");
+
+       return 0;
+}
+
+static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+
+       return 0;
+}
+
+static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+       return 0;
+}
+
+static int soc_camera_reqbufs(struct file *file, void *priv,
+                             struct v4l2_requestbuffers *p)
+{
+       int ret;
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory);
+
+       ret = videobuf_reqbufs(&icf->vb_vidq, p);
+       if (ret < 0)
+               return ret;
+
+       return ici->ops->reqbufs(icf, p);
+}
+
+static int soc_camera_querybuf(struct file *file, void *priv,
+                              struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_querybuf(&icf->vb_vidq, p);
+}
+
+static int soc_camera_qbuf(struct file *file, void *priv,
+                          struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_qbuf(&icf->vb_vidq, p);
+}
+
+static int soc_camera_dqbuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct soc_camera_file *icf = file->private_data;
+
+       WARN_ON(priv != file->private_data);
+
+       return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
+}
+
+static int soc_camera_open(struct inode *inode, struct file *file)
+{
+       struct video_device *vdev;
+       struct soc_camera_device *icd;
+       struct soc_camera_host *ici;
+       struct soc_camera_file *icf;
+       spinlock_t *lock;
+       int ret;
+
+       icf = vmalloc(sizeof(*icf));
+       if (!icf)
+               return -ENOMEM;
+
+       /* Protect against icd->remove() until we module_get() both drivers. */
+       mutex_lock(&video_lock);
+
+       vdev = video_devdata(file);
+       icd = container_of(vdev->dev, struct soc_camera_device, dev);
+       ici = to_soc_camera_host(icd->dev.parent);
+
+       if (!try_module_get(icd->ops->owner)) {
+               dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
+               ret = -EINVAL;
+               goto emgd;
+       }
+
+       if (!try_module_get(ici->ops->owner)) {
+               dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
+               ret = -EINVAL;
+               goto emgi;
+       }
+
+       icf->icd = icd;
+
+       icf->lock = ici->ops->spinlock_alloc(icf);
+       if (!icf->lock) {
+               ret = -ENOMEM;
+               goto esla;
+       }
+
+       icd->use_count++;
+
+       /* Now we really have to activate the camera */
+       if (icd->use_count == 1) {
+               ret = ici->ops->add(icd);
+               if (ret < 0) {
+                       dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
+                       icd->use_count--;
+                       goto eiciadd;
+               }
+       }
+
+       mutex_unlock(&video_lock);
+
+       file->private_data = icf;
+       dev_dbg(&icd->dev, "camera device open\n");
+
+       /* We must pass NULL as dev pointer, then all pci_* dma operations
+        * transform to normal dma_* ones. */
+       videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
+                               V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
+                               ici->msize, icd);
+
+       return 0;
+
+       /* All errors are entered with the video_lock held */
+eiciadd:
+       lock = icf->lock;
+       icf->lock = NULL;
+       if (ici->ops->spinlock_free)
+               ici->ops->spinlock_free(lock);
+esla:
+       module_put(ici->ops->owner);
+emgi:
+       module_put(icd->ops->owner);
+emgd:
+       mutex_unlock(&video_lock);
+       vfree(icf);
+       return ret;
+}
+
+static int soc_camera_close(struct inode *inode, struct file *file)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct video_device *vdev = icd->vdev;
+       spinlock_t *lock = icf->lock;
+
+       mutex_lock(&video_lock);
+       icd->use_count--;
+       if (!icd->use_count)
+               ici->ops->remove(icd);
+       icf->lock = NULL;
+       if (ici->ops->spinlock_free)
+               ici->ops->spinlock_free(lock);
+       module_put(icd->ops->owner);
+       module_put(ici->ops->owner);
+       mutex_unlock(&video_lock);
+
+       vfree(icf);
+
+       dev_dbg(vdev->dev, "camera device close\n");
+
+       return 0;
+}
+
+static ssize_t soc_camera_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *ppos)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct video_device *vdev = icd->vdev;
+       int err = -EINVAL;
+
+       dev_err(vdev->dev, "camera device read not implemented\n");
+
+       return err;
+}
+
+static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       int err;
+
+       dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
+
+       err = videobuf_mmap_mapper(&icf->vb_vidq, vma);
+
+       dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
+               err);
+
+       return err;
+}
+
+static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       if (list_empty(&icf->vb_vidq.stream)) {
+               dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
+               return POLLERR;
+       }
+
+       return ici->ops->poll(file, pt);
+}
+
+
+static struct file_operations soc_camera_fops = {
+       .owner          = THIS_MODULE,
+       .open           = soc_camera_open,
+       .release        = soc_camera_close,
+       .ioctl          = video_ioctl2,
+       .read           = soc_camera_read,
+       .mmap           = soc_camera_mmap,
+       .poll           = soc_camera_poll,
+       .llseek         = no_llseek,
+};
+
+
+static int soc_camera_s_fmt_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+       struct v4l2_rect rect;
+       const static struct soc_camera_data_format *data_fmt;
+
+       WARN_ON(priv != file->private_data);
+
+       data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
+       if (!data_fmt)
+               return -EINVAL;
+
+       /* buswidth may be further adjusted by the ici */
+       icd->buswidth = data_fmt->depth;
+
+       ret = soc_camera_try_fmt_cap(file, icf, f);
+       if (ret < 0)
+               return ret;
+
+       rect.left       = icd->x_current;
+       rect.top        = icd->y_current;
+       rect.width      = f->fmt.pix.width;
+       rect.height     = f->fmt.pix.height;
+       ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
+       if (ret < 0)
+               return ret;
+
+       icd->current_fmt        = data_fmt;
+       icd->width              = rect.width;
+       icd->height             = rect.height;
+       icf->vb_vidq.field      = f->fmt.pix.field;
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
+               dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
+                        f->type);
+
+       dev_dbg(&icd->dev, "set width: %d height: %d\n",
+               icd->width, icd->height);
+
+       /* set physical bus parameters */
+       return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
+}
+
+static int soc_camera_enum_fmt_cap(struct file *file, void  *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       const struct soc_camera_data_format *format;
+
+       WARN_ON(priv != file->private_data);
+
+       if (f->index >= icd->num_formats)
+               return -EINVAL;
+
+       format = &icd->formats[f->index];
+
+       strlcpy(f->description, format->name, sizeof(f->description));
+       f->pixelformat = format->fourcc;
+       return 0;
+}
+
+static int soc_camera_g_fmt_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       f->fmt.pix.width        = icd->width;
+       f->fmt.pix.height       = icd->height;
+       f->fmt.pix.field        = icf->vb_vidq.field;
+       f->fmt.pix.pixelformat  = icd->current_fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * icd->current_fmt->depth) >> 3;
+       f->fmt.pix.sizeimage    =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
+               icd->current_fmt->fourcc);
+       return 0;
+}
+
+static int soc_camera_querycap(struct file *file, void  *priv,
+                              struct v4l2_capability *cap)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+
+       WARN_ON(priv != file->private_data);
+
+       strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
+       return ici->ops->querycap(ici, cap);
+}
+
+static int soc_camera_streamon(struct file *file, void *priv,
+                              enum v4l2_buf_type i)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       icd->ops->start_capture(icd);
+
+       /* This calls buf_queue from host driver's videobuf_queue_ops */
+       return videobuf_streamon(&icf->vb_vidq);
+}
+
+static int soc_camera_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type i)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* This calls buf_release from host driver's videobuf_queue_ops for all
+        * remaining buffers. When the last buffer is freed, stop capture */
+       videobuf_streamoff(&icf->vb_vidq);
+
+       icd->ops->stop_capture(icd);
+
+       return 0;
+}
+
+static int soc_camera_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       int i;
+
+       WARN_ON(priv != file->private_data);
+
+       if (!qc->id)
+               return -EINVAL;
+
+       for (i = 0; i < icd->ops->num_controls; i++)
+               if (qc->id == icd->ops->controls[i].id) {
+                       memcpy(qc, &(icd->ops->controls[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+static int soc_camera_g_ctrl(struct file *file, void *priv,
+                            struct v4l2_control *ctrl)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               if (icd->gain == (unsigned short)~0)
+                       return -EINVAL;
+               ctrl->value = icd->gain;
+               return 0;
+       case V4L2_CID_EXPOSURE:
+               if (icd->exposure == (unsigned short)~0)
+                       return -EINVAL;
+               ctrl->value = icd->exposure;
+               return 0;
+       }
+
+       if (icd->ops->get_control)
+               return icd->ops->get_control(icd, ctrl);
+       return -EINVAL;
+}
+
+static int soc_camera_s_ctrl(struct file *file, void *priv,
+                            struct v4l2_control *ctrl)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       WARN_ON(priv != file->private_data);
+
+       if (icd->ops->set_control)
+               return icd->ops->set_control(icd, ctrl);
+       return -EINVAL;
+}
+
+static int soc_camera_cropcap(struct file *file, void *fh,
+                             struct v4l2_cropcap *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->bounds.left                  = icd->x_min;
+       a->bounds.top                   = icd->y_min;
+       a->bounds.width                 = icd->width_max;
+       a->bounds.height                = icd->height_max;
+       a->defrect.left                 = icd->x_min;
+       a->defrect.top                  = icd->y_min;
+       a->defrect.width                = 640;
+       a->defrect.height               = 480;
+       a->pixelaspect.numerator        = 1;
+       a->pixelaspect.denominator      = 1;
+
+       return 0;
+}
+
+static int soc_camera_g_crop(struct file *file, void *fh,
+                            struct v4l2_crop *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->c.left       = icd->x_current;
+       a->c.top        = icd->y_current;
+       a->c.width      = icd->width;
+       a->c.height     = icd->height;
+
+       return 0;
+}
+
+static int soc_camera_s_crop(struct file *file, void *fh,
+                            struct v4l2_crop *a)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       ret = ici->ops->set_fmt_cap(icd, 0, &a->c);
+       if (!ret) {
+               icd->width      = a->c.width;
+               icd->height     = a->c.height;
+               icd->x_current  = a->c.left;
+               icd->y_current  = a->c.top;
+       }
+
+       return ret;
+}
+
+static int soc_camera_g_chip_ident(struct file *file, void *fh,
+                                  struct v4l2_chip_ident *id)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->get_chip_id)
+               return -EINVAL;
+
+       return icd->ops->get_chip_id(icd, id);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int soc_camera_g_register(struct file *file, void *fh,
+                                struct v4l2_register *reg)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->get_register)
+               return -EINVAL;
+
+       return icd->ops->get_register(icd, reg);
+}
+
+static int soc_camera_s_register(struct file *file, void *fh,
+                                struct v4l2_register *reg)
+{
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+
+       if (!icd->ops->set_register)
+               return -EINVAL;
+
+       return icd->ops->set_register(icd, reg);
+}
+#endif
+
+static int device_register_link(struct soc_camera_device *icd)
+{
+       int ret = device_register(&icd->dev);
+
+       if (ret < 0) {
+               /* Prevent calling device_unregister() */
+               icd->dev.parent = NULL;
+               dev_err(&icd->dev, "Cannot register device: %d\n", ret);
+       /* Even if probe() was unsuccessful for all registered drivers,
+        * device_register() returns 0, and we add the link, just to
+        * document this camera's control device */
+       } else if (icd->control)
+               /* Have to sysfs_remove_link() before device_unregister()? */
+               if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
+                                     "control"))
+                       dev_warn(&icd->dev,
+                                "Failed creating the control symlink\n");
+       return ret;
+}
+
+/* So far this function cannot fail */
+static void scan_add_host(struct soc_camera_host *ici)
+{
+       struct soc_camera_device *icd;
+
+       mutex_lock(&list_lock);
+
+       list_for_each_entry(icd, &devices, list) {
+               if (icd->iface == ici->nr) {
+                       icd->dev.parent = &ici->dev;
+                       device_register_link(icd);
+               }
+       }
+
+       mutex_unlock(&list_lock);
+}
+
+/* return: 0 if no match found or a match found and
+ * device_register() successful, error code otherwise */
+static int scan_add_device(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici;
+       int ret = 0;
+
+       mutex_lock(&list_lock);
+
+       list_add_tail(&icd->list, &devices);
+
+       /* Watch out for class_for_each_device / class_find_device API by
+        * Dave Young <hidave.darkstar@gmail.com> */
+       list_for_each_entry(ici, &hosts, list) {
+               if (icd->iface == ici->nr) {
+                       ret = 1;
+                       icd->dev.parent = &ici->dev;
+                       break;
+               }
+       }
+
+       mutex_unlock(&list_lock);
+
+       if (ret)
+               ret = device_register_link(icd);
+
+       return ret;
+}
+
+static int soc_camera_probe(struct device *dev)
+{
+       struct soc_camera_device *icd = to_soc_camera_dev(dev);
+       struct soc_camera_host *ici =
+               to_soc_camera_host(icd->dev.parent);
+       int ret;
+
+       if (!icd->ops->probe)
+               return -ENODEV;
+
+       /* We only call ->add() here to activate and probe the camera.
+        * We shall ->remove() and deactivate it immediately afterwards. */
+       ret = ici->ops->add(icd);
+       if (ret < 0)
+               return ret;
+
+       ret = icd->ops->probe(icd);
+       if (ret >= 0) {
+               const struct v4l2_queryctrl *qctrl;
+
+               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
+               icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
+               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+               icd->exposure = qctrl ? qctrl->default_value :
+                       (unsigned short)~0;
+       }
+       ici->ops->remove(icd);
+
+       return ret;
+}
+
+/* This is called on device_unregister, which only means we have to disconnect
+ * from the host, but not remove ourselves from the device list */
+static int soc_camera_remove(struct device *dev)
+{
+       struct soc_camera_device *icd = to_soc_camera_dev(dev);
+
+       if (icd->ops->remove)
+               icd->ops->remove(icd);
+
+       return 0;
+}
+
+static struct bus_type soc_camera_bus_type = {
+       .name           = "soc-camera",
+       .probe          = soc_camera_probe,
+       .remove         = soc_camera_remove,
+};
+
+static struct device_driver ic_drv = {
+       .name   = "camera",
+       .bus    = &soc_camera_bus_type,
+       .owner  = THIS_MODULE,
+};
+
+/*
+ * Image capture host - this is a host device, not a bus device, so,
+ * no bus reference, no probing.
+ */
+static struct class soc_camera_host_class = {
+       .owner          = THIS_MODULE,
+       .name           = "camera_host",
+};
+
+static void dummy_release(struct device *dev)
+{
+}
+
+static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
+{
+       spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+       if (lock)
+               spin_lock_init(lock);
+
+       return lock;
+}
+
+static void spinlock_free(spinlock_t *lock)
+{
+       kfree(lock);
+}
+
+int soc_camera_host_register(struct soc_camera_host *ici)
+{
+       int ret;
+       struct soc_camera_host *ix;
+
+       if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
+               return -EINVAL;
+
+       /* Number might be equal to the platform device ID */
+       sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
+       ici->dev.class = &soc_camera_host_class;
+
+       mutex_lock(&list_lock);
+       list_for_each_entry(ix, &hosts, list) {
+               if (ix->nr == ici->nr) {
+                       mutex_unlock(&list_lock);
+                       return -EBUSY;
+               }
+       }
+
+       list_add_tail(&ici->list, &hosts);
+       mutex_unlock(&list_lock);
+
+       ici->dev.release = dummy_release;
+
+       ret = device_register(&ici->dev);
+
+       if (ret)
+               goto edevr;
+
+       if (!ici->ops->spinlock_alloc) {
+               ici->ops->spinlock_alloc = spinlock_alloc;
+               ici->ops->spinlock_free = spinlock_free;
+       }
+
+       scan_add_host(ici);
+
+       return 0;
+
+edevr:
+       mutex_lock(&list_lock);
+       list_del(&ici->list);
+       mutex_unlock(&list_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(soc_camera_host_register);
+
+/* Unregister all clients! */
+void soc_camera_host_unregister(struct soc_camera_host *ici)
+{
+       struct soc_camera_device *icd;
+
+       mutex_lock(&list_lock);
+
+       list_del(&ici->list);
+
+       list_for_each_entry(icd, &devices, list) {
+               if (icd->dev.parent == &ici->dev) {
+                       device_unregister(&icd->dev);
+                       /* Not before device_unregister(), .remove
+                        * needs parent to call ici->ops->remove() */
+                       icd->dev.parent = NULL;
+                       memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
+               }
+       }
+
+       mutex_unlock(&list_lock);
+
+       device_unregister(&ici->dev);
+}
+EXPORT_SYMBOL(soc_camera_host_unregister);
+
+/* Image capture device */
+int soc_camera_device_register(struct soc_camera_device *icd)
+{
+       struct soc_camera_device *ix;
+       int num = -1, i;
+
+       if (!icd)
+               return -EINVAL;
+
+       for (i = 0; i < 256 && num < 0; i++) {
+               num = i;
+               list_for_each_entry(ix, &devices, list) {
+                       if (ix->iface == icd->iface && ix->devnum == i) {
+                               num = -1;
+                               break;
+                       }
+               }
+       }
+
+       if (num < 0)
+               /* ok, we have 256 cameras on this host...
+                * man, stay reasonable... */
+               return -ENOMEM;
+
+       icd->devnum = num;
+       icd->dev.bus = &soc_camera_bus_type;
+       snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
+                "%u-%u", icd->iface, icd->devnum);
+
+       icd->dev.release = dummy_release;
+
+       return scan_add_device(icd);
+}
+EXPORT_SYMBOL(soc_camera_device_register);
+
+void soc_camera_device_unregister(struct soc_camera_device *icd)
+{
+       mutex_lock(&list_lock);
+       list_del(&icd->list);
+
+       /* The bus->remove will be eventually called */
+       if (icd->dev.parent)
+               device_unregister(&icd->dev);
+       mutex_unlock(&list_lock);
+}
+EXPORT_SYMBOL(soc_camera_device_unregister);
+
+int soc_camera_video_start(struct soc_camera_device *icd)
+{
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       int err = -ENOMEM;
+       struct video_device *vdev;
+
+       if (!icd->dev.parent)
+               return -ENODEV;
+
+       vdev = video_device_alloc();
+       if (!vdev)
+               goto evidallocd;
+       dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
+
+       strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
+       /* Maybe better &ici->dev */
+       vdev->dev               = &icd->dev;
+       vdev->type              = VID_TYPE_CAPTURE;
+       vdev->current_norm      = V4L2_STD_UNKNOWN;
+       vdev->fops              = &soc_camera_fops;
+       vdev->release           = video_device_release;
+       vdev->minor             = -1;
+       vdev->tvnorms           = V4L2_STD_UNKNOWN,
+       vdev->vidioc_querycap   = soc_camera_querycap;
+       vdev->vidioc_g_fmt_cap  = soc_camera_g_fmt_cap;
+       vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap;
+       vdev->vidioc_s_fmt_cap  = soc_camera_s_fmt_cap;
+       vdev->vidioc_enum_input = soc_camera_enum_input;
+       vdev->vidioc_g_input    = soc_camera_g_input;
+       vdev->vidioc_s_input    = soc_camera_s_input;
+       vdev->vidioc_s_std      = soc_camera_s_std;
+       vdev->vidioc_reqbufs    = soc_camera_reqbufs;
+       vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap;
+       vdev->vidioc_querybuf   = soc_camera_querybuf;
+       vdev->vidioc_qbuf       = soc_camera_qbuf;
+       vdev->vidioc_dqbuf      = soc_camera_dqbuf;
+       vdev->vidioc_streamon   = soc_camera_streamon;
+       vdev->vidioc_streamoff  = soc_camera_streamoff;
+       vdev->vidioc_queryctrl  = soc_camera_queryctrl;
+       vdev->vidioc_g_ctrl     = soc_camera_g_ctrl;
+       vdev->vidioc_s_ctrl     = soc_camera_s_ctrl;
+       vdev->vidioc_cropcap    = soc_camera_cropcap;
+       vdev->vidioc_g_crop     = soc_camera_g_crop;
+       vdev->vidioc_s_crop     = soc_camera_s_crop;
+       vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       vdev->vidioc_g_register = soc_camera_g_register;
+       vdev->vidioc_s_register = soc_camera_s_register;
+#endif
+
+       icd->current_fmt = &icd->formats[0];
+
+       err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
+       if (err < 0) {
+               dev_err(vdev->dev, "video_register_device failed\n");
+               goto evidregd;
+       }
+       icd->vdev = vdev;
+
+       return 0;
+
+evidregd:
+       video_device_release(vdev);
+evidallocd:
+       return err;
+}
+EXPORT_SYMBOL(soc_camera_video_start);
+
+void soc_camera_video_stop(struct soc_camera_device *icd)
+{
+       struct video_device *vdev = icd->vdev;
+
+       dev_dbg(&icd->dev, "%s\n", __func__);
+
+       if (!icd->dev.parent || !vdev)
+               return;
+
+       mutex_lock(&video_lock);
+       video_unregister_device(vdev);
+       icd->vdev = NULL;
+       mutex_unlock(&video_lock);
+}
+EXPORT_SYMBOL(soc_camera_video_stop);
+
+static int __init soc_camera_init(void)
+{
+       int ret = bus_register(&soc_camera_bus_type);
+       if (ret)
+               return ret;
+       ret = driver_register(&ic_drv);
+       if (ret)
+               goto edrvr;
+       ret = class_register(&soc_camera_host_class);
+       if (ret)
+               goto eclr;
+
+       return 0;
+
+eclr:
+       driver_unregister(&ic_drv);
+edrvr:
+       bus_unregister(&soc_camera_bus_type);
+       return ret;
+}
+
+static void __exit soc_camera_exit(void)
+{
+       class_unregister(&soc_camera_host_class);
+       driver_unregister(&ic_drv);
+       bus_unregister(&soc_camera_bus_type);
+}
+
+module_init(soc_camera_init);
+module_exit(soc_camera_exit);
+
+MODULE_DESCRIPTION("Image capture bus driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
index ceba45ad02942622edd1c67f8aecb9d65306c1e7..9276ed99738839075615554ff384e5afd285815b 100644 (file)
@@ -1100,7 +1100,7 @@ static int stk_setup_format(struct stk_camera *dev)
                        && i < ARRAY_SIZE(stk_sizes))
                i++;
        if (i == ARRAY_SIZE(stk_sizes)) {
-               STK_ERROR("Something is broken in %s\n", __FUNCTION__);
+               STK_ERROR("Something is broken in %s\n", __func__);
                return -EFAULT;
        }
        /* This registers controls some timings, not sure of what. */
@@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
 }
 
 #ifdef CONFIG_PM
-int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct stk_camera *dev = usb_get_intfdata(intf);
        if (is_streaming(dev)) {
@@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
        return 0;
 }
 
-int stk_camera_resume(struct usb_interface *intf)
+static int stk_camera_resume(struct usb_interface *intf)
 {
        struct stk_camera *dev = usb_get_intfdata(intf);
        if (!is_initialised(dev))
index 3fb85af5d1f2b8ab45140661298a53062c920fb3..c109511f21ea8a92b307d4ce1596748567c0348f 100644 (file)
@@ -58,7 +58,7 @@
 
 static struct saa7146 saa7146s[SAA7146_MAX];
 
-static int saa_num = 0;                /* number of SAA7146s in use */
+static int saa_num;            /* number of SAA7146s in use */
 
 static int video_nr = -1;
 module_param(video_nr, int, 0);
@@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa)
                        attach_inform(saa, i);
 }
 
-static int debiwait_maxwait = 0;
+static int debiwait_maxwait;
 
 static int wait_for_debi_done(struct saa7146 *saa)
 {
@@ -1906,7 +1906,9 @@ static const struct file_operations saa_fops = {
        .open = saa_open,
        .release = saa_release,
        .ioctl = saa_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read = saa_read,
        .llseek = no_llseek,
        .write = saa_write,
index afc32aa56fde2eb3952cb69dd214cdd9cd52701b..d7f130bedb5f47a05f6eddff87634e6af54d25c4 100644 (file)
 #include "stv680.h"
 
 static int video_nr = -1;
-static int swapRGB = 0;   /* default for auto sleect */
-static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
 
-static unsigned int debug = 0;
+static int swapRGB;    /* 0 = default for auto select */
+
+/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */
+static int swapRGB_on;
+
+static unsigned int debug;
 
 #define PDEBUG(level, fmt, args...) \
        do { \
        if (debug >= level)     \
-               info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \
+               info("[%s:%d] " fmt, __func__, __LINE__ , ## args);     \
        } while (0)
 
 
@@ -1391,7 +1394,9 @@ static const struct file_operations stv680_fops = {
        .read =         stv680_read,
        .mmap =         stv680_mmap,
        .ioctl =        stv680_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek =       no_llseek,
 };
 static struct video_device stv680_template = {
index fb895f6684a3cf31851323afa4ef5db03e84c762..6943b447a1bd7f4067e4a6f97a92c9e6d67ef83e 100644 (file)
@@ -906,7 +906,7 @@ static int __init tcm825x_init(void)
        rval = i2c_add_driver(&tcm825x_i2c_driver);
        if (rval)
                printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
-                      __FUNCTION__);
+                      __func__);
 
        return rval;
 }
index 55bc89a6f0694c7f3d8e35e6804f4fb8d01eda5f..0ebb5b525e576da86f021b74b669f5493e4886db 100644 (file)
@@ -32,8 +32,6 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tda8290"
-
 /* ---------------------------------------------------------------------- */
 
 struct tda8290_priv {
@@ -174,7 +172,7 @@ static void tda8290_set_params(struct dvb_frontend *fe,
        set_audio(fe, params);
 
        if (priv->cfg.config)
-               tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config);
+               tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
        tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
        tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
        tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
@@ -365,7 +363,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
 
        set_audio(fe, params);
 
-       tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
+       tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
 
        tda8295_power(fe, 1);
        tda8295_agc1_out(fe, 1);
@@ -444,8 +442,7 @@ static void tda8290_init_if(struct dvb_frontend *fe)
        unsigned char set_GP00_CF[] = { 0x20, 0x01 };
        unsigned char set_GP01_CF[] = { 0x20, 0x0B };
 
-       if ((priv->cfg.config) &&
-           ((*priv->cfg.config == 1) || (*priv->cfg.config == 2)))
+       if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
                tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
        else
                tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
@@ -590,8 +587,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
                else
                        priv->ver |= TDA8275A;
 
-               tda827x_attach(fe, priv->tda827x_addr,
-                              priv->i2c_props.adap, &priv->cfg);
+               tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
+               priv->cfg.switch_addr = priv->i2c_props.addr;
        }
        if (fe->ops.tuner_ops.init)
                fe->ops.tuner_ops.init(fe);
@@ -616,7 +613,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props)
        if (tda8290_id[1] == TDA8290_ID) {
                if (debug)
                        printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
-                              __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+                              __func__, i2c_adapter_id(i2c_props->adap),
                               i2c_props->addr);
                return 0;
        }
@@ -636,7 +633,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
        if (tda8295_id[1] == TDA8295_ID) {
                if (debug)
                        printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
-                              __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+                              __func__, i2c_adapter_id(i2c_props->adap),
                               i2c_props->addr);
                return 0;
        }
@@ -674,6 +671,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr     = i2c_addr;
        priv->i2c_props.adap     = i2c_adap;
+       priv->i2c_props.name     = "tda829x";
        if (cfg) {
                priv->cfg.config         = cfg->lna_cfg;
                priv->cfg.tuner_callback = cfg->tuner_callback;
index dc8ef310b7b26b1fbccc6e24d321eb70d63caba2..d3bbf276a469165354e82770764feec9d619bec6 100644 (file)
@@ -21,7 +21,7 @@
 #include "dvb_frontend.h"
 
 struct tda829x_config {
-       unsigned int *lna_cfg;
+       unsigned int lna_cfg;
        int (*tuner_callback) (void *dev, int command, int arg);
 
        unsigned int probe_tuner:1;
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
 #else
 static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return -EINVAL;
 }
 
@@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
                                                  struct tda829x_config *cfg)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return NULL;
 }
 #endif
index bdca5d278978374b7a65e7e55bd65aa06a010ee2..0cee00242782bb0ec16a0736b822d43370cd9624 100644 (file)
 
 #include "tda9840.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 #define        SWITCH          0x00
 #define        LEVEL_ADJUST    0x02
index 106c93b8203fea587562240b37b8d0564cbb21a3..a0545ba957b05c5be756016ebb041d792088006d 100644 (file)
@@ -25,10 +25,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tda9887"
+static DEFINE_MUTEX(tda9887_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
 
 struct tda9887_priv {
        struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
 
        unsigned char      data[4];
        unsigned int       config;
@@ -644,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
 
 static void tda9887_release(struct dvb_frontend *fe)
 {
-       kfree(fe->analog_demod_priv);
+       struct tda9887_priv *priv = fe->analog_demod_priv;
+
+       mutex_lock(&tda9887_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&tda9887_list_mutex);
+
        fe->analog_demod_priv = NULL;
 }
 
@@ -665,17 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                    u8 i2c_addr)
 {
        struct tda9887_priv *priv = NULL;
+       int instance;
 
-       priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
-       if (priv == NULL)
-               return NULL;
-       fe->analog_demod_priv = priv;
+       mutex_lock(&tda9887_list_mutex);
 
-       priv->i2c_props.addr = i2c_addr;
-       priv->i2c_props.adap = i2c_adap;
-       priv->mode = T_STANDBY;
+       instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c_adap, i2c_addr, "tda9887");
+       switch (instance) {
+       case 0:
+               mutex_unlock(&tda9887_list_mutex);
+               return NULL;
+               break;
+       case 1:
+               fe->analog_demod_priv = priv;
+               priv->mode = T_STANDBY;
+               tuner_info("tda988[5/6/7] found\n");
+               break;
+       default:
+               fe->analog_demod_priv = priv;
+               break;
+       }
 
-       tuner_info("tda988[5/6/7] found\n");
+       mutex_unlock(&tda9887_list_mutex);
 
        memcpy(&fe->ops.analog_ops, &tda9887_ops,
               sizeof(struct analog_demod_ops));
index 8f873a8e6ed20ef80b16ff2dfe4bdf4809be33ab..be49dcbfc70e1473056823b24e7a7f0d7bec56d2 100644 (file)
@@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c_adap,
                                                  u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 5326eeceaacdabb0bdce32825182924fd8d65f35..b93cdef9ac73e48b04f5a369da3767e6d46c42d7 100644 (file)
 #include "tuner-i2c.h"
 #include "tea5761.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tea5761"
-
 struct tea5761_priv {
        struct tuner_i2c_props i2c_props;
 
@@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer)
 
        frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4;      /* Freq in KHz */
 
-       printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+       printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
               frq / 1000, frq % 1000, div);
 }
 
@@ -249,14 +247,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
 
        if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
                printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
-               return EINVAL;
+               return -EINVAL;
        }
 
-       if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
-               printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
-               return EINVAL;
+       if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
+               printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
+                                   " It is not a TEA5761\n",
+                                   buffer[13], buffer[14], buffer[15]);
+               return -EINVAL;
        }
-       printk(KERN_WARNING "TEA5761 detected.\n");
+       printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
+                           "Manufacturer ID= 0x%02x\n",
+                           buffer[14], buffer[15], buffer[13]);
+
        return 0;
 }
 
@@ -302,6 +305,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr = i2c_addr;
        priv->i2c_props.adap = i2c_adap;
+       priv->i2c_props.name = "tea5761";
 
        memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
               sizeof(struct dvb_tuner_ops));
index 73a03b427843f4466a3043c68eb6dc14a36a1b2b..8eb62722b9885f7d4253200a128401b416736c65 100644 (file)
@@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
                                        u8 i2c_addr)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return -EINVAL;
 }
 
@@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter* i2c_adap,
                                                   u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index e1b48d87e7b74fba277b9796e074bf13b514bd86..f6e7d7ad842416ad5ac9b82bde9532125a3ddd80 100644 (file)
 #include "tuner-i2c.h"
 #include "tea5767.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tea5767"
-
 /*****************************************************************************/
 
 struct tea5767_priv {
@@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
        unsigned int div, frq;
 
        if (TEA5767_READY_FLAG_MASK & buffer[0])
-               printk(PREFIX "Ready Flag ON\n");
+               tuner_info("Ready Flag ON\n");
        else
-               printk(PREFIX "Ready Flag OFF\n");
+               tuner_info("Ready Flag OFF\n");
 
        if (TEA5767_BAND_LIMIT_MASK & buffer[0])
-               printk(PREFIX "Tuner at band limit\n");
+               tuner_info("Tuner at band limit\n");
        else
-               printk(PREFIX "Tuner not at band limit\n");
+               tuner_info("Tuner not at band limit\n");
 
        div = ((buffer[0] & 0x3f) << 8) | buffer[1];
 
@@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
        buffer[0] = (div >> 8) & 0x3f;
        buffer[1] = div & 0xff;
 
-       printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
-              frq / 1000, frq % 1000, div);
+       tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
+                  frq / 1000, frq % 1000, div);
 
        if (TEA5767_STEREO_MASK & buffer[2])
-               printk(PREFIX "Stereo\n");
+               tuner_info("Stereo\n");
        else
-               printk(PREFIX "Mono\n");
+               tuner_info("Mono\n");
 
-       printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
+       tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
 
-       printk(PREFIX "ADC Level = %d\n",
-              (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
+       tuner_info("ADC Level = %d\n",
+                  (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
 
-       printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
+       tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
 
-       printk(PREFIX "Reserved = 0x%02x\n",
-              (buffer[4] & TEA5767_RESERVED_MASK));
+       tuner_info("Reserved = 0x%02x\n",
+                  (buffer[4] & TEA5767_RESERVED_MASK));
 }
 
 /* Freq should be specifyed at 62.5 Hz */
@@ -395,11 +393,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
                return EINVAL;
        }
 
-       /* It seems that tea5767 returns 0xff after the 5th byte */
-       if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
-               printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
-               return EINVAL;
-       }
 
        return 0;
 }
@@ -456,6 +449,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
 
        priv->i2c_props.addr  = i2c_addr;
        priv->i2c_props.adap  = i2c_adap;
+       priv->i2c_props.name  = "tea5767";
+
        priv->ctrl.xtal_freq  = TEA5767_HIGH_LO_32768;
        priv->ctrl.port1      = 1;
        priv->ctrl.port2      = 1;
index a44451f6114544ea689afa716cae716d559f47bf..7b547c092e25215bbd81505b8635c7ec907611bc 100644 (file)
@@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
                                        u8 i2c_addr)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return -EINVAL;
 }
 
@@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
                                                   struct i2c_adapter* i2c_adap,
                                                   u8 i2c_addr)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index df2fad9f391eb0a2936b8c14c39c51a1273a0e0c..9513d8611e8781431db6306fb5a2c8645df19817 100644 (file)
 
 #include "tea6415c.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 #define TEA6415C_NUM_INPUTS    8
 #define TEA6415C_NUM_OUTPUTS   6
index 4ff6c63f7237517a05d974fd60cfbcbb838af0cf..7fd53367c07caef877db4d21b55dbfc8d6355147 100644 (file)
 
 #include "tea6420.h"
 
-static int debug = 0;          /* insmod parameter */
+static int debug;              /* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
 
 /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
index 78a09a2a4857b94028e7eadbbecb37dea0c91908..529e00952a8db1c0b813f8f3ae06c1d62d067e3b 100644 (file)
@@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = {
 I2C_CLIENT_INSMOD;
 
 /* insmod options used at init time => read/only */
-static unsigned int addr = 0;
-static unsigned int no_autodetect = 0;
-static unsigned int show_i2c = 0;
+static unsigned int addr;
+static unsigned int no_autodetect;
+static unsigned int show_i2c;
 
 /* insmod options used at runtime => read/write */
 static int tuner_debug;
@@ -313,24 +313,14 @@ static void tuner_i2c_address_check(struct tuner *t)
        tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
        tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
        tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
-                  t->i2c->adapter->name, t->i2c->addr, t->type,
-                  tuners[t->type].name);
+                  t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
        tuner_warn("====================== WARNING! ======================\n");
 }
 
-static void attach_simple_tuner(struct tuner *t)
-{
-       struct simple_tuner_config cfg = {
-               .type = t->type,
-               .tun  = &tuners[t->type]
-       };
-       simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
-}
-
 static void attach_tda829x(struct tuner *t)
 {
        struct tda829x_config cfg = {
-               .lna_cfg        = &t->config,
+               .lna_cfg        = t->config,
                .tuner_callback = t->tuner_callback,
        };
        tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
@@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
                return;
        }
 
-       if (type >= tuner_count) {
-               tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
-               return;
-       }
-
        t->type = type;
        t->config = new_config;
        if (tuner_callback != NULL) {
@@ -409,7 +394,12 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
+                                       t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        case TUNER_PHILIPS_TD1316:
                buffer[0] = 0x0b;
@@ -417,14 +407,18 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
                i2c_master_send(c,buffer,4);
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        case TUNER_XC2028:
        {
                struct xc2028_config cfg = {
                        .i2c_adap  = t->i2c->adapter,
                        .i2c_addr  = t->i2c->addr,
-                       .video_dev = c->adapter->algo_data,
                        .callback  = t->tuner_callback,
                };
                if (!xc2028_attach(&t->fe, &cfg)) {
@@ -455,7 +449,12 @@ static void set_type(struct i2c_client *c, unsigned int type,
                }
                break;
        default:
-               attach_simple_tuner(t);
+               if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+                                       t->i2c->addr, t->type) == NULL) {
+                       t->type = TUNER_ABSENT;
+                       t->mode_mask = T_UNINITIALIZED;
+                       return;
+               }
                break;
        }
 
@@ -759,7 +758,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                if (analog_ops->standby)
                        analog_ops->standby(&t->fe);
                break;
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
        case VIDIOCSAUDIO:
                if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
                        return 0;
@@ -1112,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client)
        if (!no_autodetect) {
                switch (client->addr) {
                case 0x10:
-                       if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
-                                       != EINVAL) {
+                       if (tea5761_autodetection(t->i2c->adapter,
+                                                 t->i2c->addr) >= 0) {
                                t->type = TUNER_TEA5761;
                                t->mode_mask = T_RADIO;
                                t->mode = T_STANDBY;
@@ -1125,7 +1124,7 @@ static int tuner_probe(struct i2c_client *client)
 
                                goto register_client;
                        }
-                       break;
+                       return -ENODEV;
                case 0x42:
                case 0x43:
                case 0x4a:
index de52e8ffd347df1dcd2060c2e6c406b0a58933c2..3ad6c8e0b04ccbd8d612ac89db2f61911b64e225 100644 (file)
 struct tuner_i2c_props {
        u8 addr;
        struct i2c_adapter *adap;
+
+       /* used for tuner instance management */
+       int count;
+       char *name;
 };
 
 static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
@@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
        return (ret == 2) ? ilen : ret;
 }
 
-#define tuner_warn(fmt, arg...) do {                                   \
-       printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX,                 \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr, ##arg);                   \
+/* Callers must declare as a global for the module:
+ *
+ * static LIST_HEAD(hybrid_tuner_instance_list);
+ *
+ * hybrid_tuner_instance_list should be the third argument
+ * passed into hybrid_tuner_request_state().
+ *
+ * state structure must contain the following:
+ *
+ *     struct list_head        hybrid_tuner_instance_list;
+ *     struct tuner_i2c_props  i2c_props;
+ *
+ * hybrid_tuner_instance_list (both within state structure and globally)
+ * is only required if the driver is using hybrid_tuner_request_state
+ * and hybrid_tuner_release_state to manage state sharing between
+ * multiple instances of hybrid tuners.
+ */
+
+#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do {              \
+       printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name,               \
+                       i2cprops.adap ?                                 \
+                               i2c_adapter_id(i2cprops.adap) : -1,     \
+                       i2cprops.addr, ##arg);                          \
         } while (0)
 
-#define tuner_info(fmt, arg...) do {                                   \
-       printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,                    \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+/* TO DO: convert all callers of these macros to pass in
+ * struct tuner_i2c_props, then remove the macro wrappers */
+
+#define __tuner_warn(i2cprops, fmt, arg...) do {                       \
+       tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg);               \
        } while (0)
 
-#define tuner_err(fmt, arg...) do {                                    \
-       printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX,                     \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+#define __tuner_info(i2cprops, fmt, arg...) do {                       \
+       tuner_printk(KERN_INFO, i2cprops, fmt, ##arg);                  \
        } while (0)
 
-#define tuner_dbg(fmt, arg...) do {                                    \
+#define __tuner_err(i2cprops, fmt, arg...) do {                                \
+       tuner_printk(KERN_ERR, i2cprops, fmt, ##arg);                   \
+       } while (0)
+
+#define __tuner_dbg(i2cprops, fmt, arg...) do {                                \
        if ((debug))                                                    \
-               printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,           \
-                       i2c_adapter_id(priv->i2c_props.adap),           \
-                       priv->i2c_props.addr , ##arg);                  \
+               tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg);         \
        } while (0)
 
+#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
+#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
+#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
+#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
+
+/****************************************************************************/
+
+/* The return value of hybrid_tuner_request_state indicates the number of
+ * instances using this tuner object.
+ *
+ * 0 - no instances, indicates an error - kzalloc must have failed
+ *
+ * 1 - one instance, indicates that the tuner object was created successfully
+ *
+ * 2 (or more) instances, indicates that an existing tuner object was found
+ */
+
+#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
+({                                                                     \
+       int __ret = 0;                                                  \
+       list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
+               if (((i2cadap) && (state->i2c_props.adap)) &&           \
+                   ((i2c_adapter_id(state->i2c_props.adap) ==          \
+                     i2c_adapter_id(i2cadap)) &&                       \
+                    (i2caddr == state->i2c_props.addr))) {             \
+                       __tuner_info(state->i2c_props,                  \
+                                    "attaching existing instance\n");  \
+                       state->i2c_props.count++;                       \
+                       __ret = state->i2c_props.count;                 \
+                       break;                                          \
+               }                                                       \
+       }                                                               \
+       if (0 == __ret) {                                               \
+               state = kzalloc(sizeof(type), GFP_KERNEL);              \
+               if (NULL == state)                                      \
+                       goto __fail;                                    \
+               state->i2c_props.addr = i2caddr;                        \
+               state->i2c_props.adap = i2cadap;                        \
+               state->i2c_props.name = devname;                        \
+               __tuner_info(state->i2c_props,                          \
+                            "creating new instance\n");                \
+               list_add_tail(&state->hybrid_tuner_instance_list, &list);\
+               state->i2c_props.count++;                               \
+               __ret = state->i2c_props.count;                         \
+       }                                                               \
+__fail:                                                                        \
+       __ret;                                                          \
+})
+
+#define hybrid_tuner_release_state(state)                              \
+({                                                                     \
+       int __ret;                                                      \
+       state->i2c_props.count--;                                       \
+       __ret = state->i2c_props.count;                                 \
+       if (!state->i2c_props.count) {                                  \
+               __tuner_info(state->i2c_props, "destroying instance\n");\
+               list_del(&state->hybrid_tuner_instance_list);           \
+               kfree(state);                                           \
+       }                                                               \
+       __ret;                                                          \
+})
+
 #endif /* __TUNER_I2C_H__ */
index c1db576696c6d34288e2b4cc6a596c4e730f9dc9..be8d903171b7dce5f3ace750c63177a86d107284 100644 (file)
 #include "tuner-i2c.h"
 #include "tuner-simple.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
-#define PREFIX "tuner-simple"
+#define TUNER_SIMPLE_MAX 64
+static unsigned int simple_devcount;
 
-static int offset = 0;
+static int offset;
 module_param(offset, int, 0664);
-MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
+
+static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
+                       { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
+                       { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
+module_param_array(atv_input, int, NULL, 0644);
+module_param_array(dtv_input, int, NULL, 0644);
+MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
+MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
 
 /* ---------------------------------------------------------------------- */
 
@@ -36,8 +46,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
  */
 #define TEMIC_SET_PAL_I         0x05
 #define TEMIC_SET_PAL_DK        0x09
-#define TEMIC_SET_PAL_L         0x0a // SECAM ?
-#define TEMIC_SET_PAL_L2        0x0b // change IF !
+#define TEMIC_SET_PAL_L         0x0a /* SECAM ? */
+#define TEMIC_SET_PAL_L2        0x0b /* change IF ! */
 #define TEMIC_SET_PAL_BG        0x0c
 
 /* tv tuner system standard selection for Philips FQ1216ME
@@ -90,14 +100,21 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
 #define TUNER_PLL_LOCKED   0x40
 #define TUNER_STEREO_MK3   0x04
 
+static DEFINE_MUTEX(tuner_simple_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
 struct tuner_simple_priv {
+       unsigned int nr;
        u16 last_div;
+
        struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
 
        unsigned int type;
        struct tunertype *tun;
 
        u32 frequency;
+       u32 bandwidth;
 };
 
 /* ---------------------------------------------------------------------- */
@@ -107,7 +124,7 @@ static int tuner_read_status(struct dvb_frontend *fe)
        struct tuner_simple_priv *priv = fe->tuner_priv;
        unsigned char byte;
 
-       if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1))
+       if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
                return 0;
 
        return byte;
@@ -121,13 +138,13 @@ static inline int tuner_signal(const int status)
 static inline int tuner_stereo(const int type, const int status)
 {
        switch (type) {
-               case TUNER_PHILIPS_FM1216ME_MK3:
-               case TUNER_PHILIPS_FM1236_MK3:
-               case TUNER_PHILIPS_FM1256_IH3:
-               case TUNER_LG_NTSC_TAPE:
-                       return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
-               default:
-                       return status & TUNER_STEREO;
+       case TUNER_PHILIPS_FM1216ME_MK3:
+       case TUNER_PHILIPS_FM1236_MK3:
+       case TUNER_PHILIPS_FM1256_IH3:
+       case TUNER_LG_NTSC_TAPE:
+               return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+       default:
+               return status & TUNER_STEREO;
        }
 }
 
@@ -145,7 +162,12 @@ static inline int tuner_afcstatus(const int status)
 static int simple_get_status(struct dvb_frontend *fe, u32 *status)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
-       int tuner_status = tuner_read_status(fe);
+       int tuner_status;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       tuner_status = tuner_read_status(fe);
 
        *status = 0;
 
@@ -162,7 +184,12 @@ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
 static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
-       int signal = tuner_signal(tuner_read_status(fe));
+       int signal;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       signal = tuner_signal(tuner_read_status(fe));
 
        *strength = signal;
 
@@ -173,174 +200,378 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
 
 /* ---------------------------------------------------------------------- */
 
-static int simple_set_tv_freq(struct dvb_frontend *fe,
-                             struct analog_parameters *params)
+static inline char *tuner_param_name(enum param_type type)
 {
-       struct tuner_simple_priv *priv = fe->tuner_priv;
-       u8 config, cb, tuneraddr;
-       u16 div;
-       struct tunertype *tun;
-       u8 buffer[4];
-       int rc, IFPCoff, i, j;
-       enum param_type desired_type;
-       struct tuner_params *t_params;
+       char *name;
 
-       tun = priv->tun;
+       switch (type) {
+       case TUNER_PARAM_TYPE_RADIO:
+               name = "radio";
+               break;
+       case TUNER_PARAM_TYPE_PAL:
+               name = "pal";
+               break;
+       case TUNER_PARAM_TYPE_SECAM:
+               name = "secam";
+               break;
+       case TUNER_PARAM_TYPE_NTSC:
+               name = "ntsc";
+               break;
+       case TUNER_PARAM_TYPE_DIGITAL:
+               name = "digital";
+               break;
+       default:
+               name = "unknown";
+               break;
+       }
+       return name;
+}
 
-       /* IFPCoff = Video Intermediate Frequency - Vif:
-               940  =16*58.75  NTSC/J (Japan)
-               732  =16*45.75  M/N STD
-               704  =16*44     ATSC (at DVB code)
-               632  =16*39.50  I U.K.
-               622.4=16*38.90  B/G D/K I, L STD
-               592  =16*37.00  D China
-               590  =16.36.875 B Australia
-               543.2=16*33.95  L' STD
-               171.2=16*10.70  FM Radio (at set_radio_freq)
-       */
+static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
+                                               enum param_type desired_type)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       struct tunertype *tun = priv->tun;
+       int i;
 
-       if (params->std == V4L2_STD_NTSC_M_JP) {
-               IFPCoff      = 940;
-               desired_type = TUNER_PARAM_TYPE_NTSC;
-       } else if ((params->std & V4L2_STD_MN) &&
-                 !(params->std & ~V4L2_STD_MN)) {
-               IFPCoff      = 732;
-               desired_type = TUNER_PARAM_TYPE_NTSC;
-       } else if (params->std == V4L2_STD_SECAM_LC) {
-               IFPCoff      = 543;
-               desired_type = TUNER_PARAM_TYPE_SECAM;
-       } else {
-               IFPCoff      = 623;
-               desired_type = TUNER_PARAM_TYPE_PAL;
-       }
+       for (i = 0; i < tun->count; i++)
+               if (desired_type == tun->params[i].type)
+                       break;
 
-       for (j = 0; j < tun->count-1; j++) {
-               if (desired_type != tun->params[j].type)
-                       continue;
-               break;
-       }
-       /* use default tuner_t_params if desired_type not available */
-       if (desired_type != tun->params[j].type) {
-               tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n",
-                         IFPCoff, priv->type);
-               j = 0;
+       /* use default tuner params if desired_type not available */
+       if (i == tun->count) {
+               tuner_dbg("desired params (%s) undefined for tuner %d\n",
+                         tuner_param_name(desired_type), priv->type);
+               i = 0;
        }
-       t_params = &tun->params[j];
+
+       tuner_dbg("using tuner params #%d (%s)\n", i,
+                 tuner_param_name(tun->params[i].type));
+
+       return &tun->params[i];
+}
+
+static int simple_config_lookup(struct dvb_frontend *fe,
+                               struct tuner_params *t_params,
+                               int *frequency, u8 *config, u8 *cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       int i;
 
        for (i = 0; i < t_params->count; i++) {
-               if (params->frequency > t_params->ranges[i].limit)
+               if (*frequency > t_params->ranges[i].limit)
                        continue;
                break;
        }
        if (i == t_params->count) {
-               tuner_dbg("TV frequency out of range (%d > %d)",
-                               params->frequency, t_params->ranges[i - 1].limit);
-               params->frequency = t_params->ranges[--i].limit;
+               tuner_dbg("frequency out of range (%d > %d)\n",
+                         *frequency, t_params->ranges[i - 1].limit);
+               *frequency = t_params->ranges[--i].limit;
        }
-       config = t_params->ranges[i].config;
-       cb     = t_params->ranges[i].cb;
-       /*  i == 0 -> VHF_LO
-        *  i == 1 -> VHF_HI
-        *  i == 2 -> UHF     */
-       tuner_dbg("tv: param %d, range %d\n",j,i);
+       *config = t_params->ranges[i].config;
+       *cb     = t_params->ranges[i].cb;
+
+       tuner_dbg("freq = %d.%02d (%d), range = %d, "
+                 "config = 0x%02x, cb = 0x%02x\n",
+                 *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
+                 i, *config, *cb);
+
+       return i;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void simple_set_rf_input(struct dvb_frontend *fe,
+                               u8 *config, u8 *cb, unsigned int rf)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
 
-       div=params->frequency + IFPCoff + offset;
+       switch (priv->type) {
+       case TUNER_PHILIPS_TUV1236D:
+               switch (rf) {
+               case 1:
+                       *cb |= 0x08;
+                       break;
+               default:
+                       *cb &= ~0x08;
+                       break;
+               }
+               break;
+       case TUNER_PHILIPS_FCV1236D:
+               switch (rf) {
+               case 1:
+                       *cb |= 0x01;
+                       break;
+               default:
+                       *cb &= ~0x01;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+}
 
-       tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
-                                       params->frequency / 16, params->frequency % 16 * 100 / 16,
-                                       IFPCoff / 16, IFPCoff % 16 * 100 / 16,
-                                       offset / 16, offset % 16 * 100 / 16,
-                                       div);
+static int simple_std_setup(struct dvb_frontend *fe,
+                           struct analog_parameters *params,
+                           u8 *config, u8 *cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u8 tuneraddr;
+       int rc;
 
        /* tv norm specific stuff for multi-norm tuners */
        switch (priv->type) {
-       case TUNER_PHILIPS_SECAM: // FI1216MF
+       case TUNER_PHILIPS_SECAM: /* FI1216MF */
                /* 0x01 -> ??? no change ??? */
                /* 0x02 -> PAL BDGHI / SECAM L */
                /* 0x04 -> ??? PAL others / SECAM others ??? */
-               cb &= ~0x03;
-               if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
-                       cb |= PHILIPS_MF_SET_STD_L;
+               *cb &= ~0x03;
+               if (params->std & V4L2_STD_SECAM_L)
+                       /* also valid for V4L2_STD_SECAM */
+                       *cb |= PHILIPS_MF_SET_STD_L;
                else if (params->std & V4L2_STD_SECAM_LC)
-                       cb |= PHILIPS_MF_SET_STD_LC;
+                       *cb |= PHILIPS_MF_SET_STD_LC;
                else /* V4L2_STD_B|V4L2_STD_GH */
-                       cb |= PHILIPS_MF_SET_STD_BG;
+                       *cb |= PHILIPS_MF_SET_STD_BG;
                break;
 
        case TUNER_TEMIC_4046FM5:
-               cb &= ~0x0f;
+               *cb &= ~0x0f;
 
                if (params->std & V4L2_STD_PAL_BG) {
-                       cb |= TEMIC_SET_PAL_BG;
+                       *cb |= TEMIC_SET_PAL_BG;
 
                } else if (params->std & V4L2_STD_PAL_I) {
-                       cb |= TEMIC_SET_PAL_I;
+                       *cb |= TEMIC_SET_PAL_I;
 
                } else if (params->std & V4L2_STD_PAL_DK) {
-                       cb |= TEMIC_SET_PAL_DK;
+                       *cb |= TEMIC_SET_PAL_DK;
 
                } else if (params->std & V4L2_STD_SECAM_L) {
-                       cb |= TEMIC_SET_PAL_L;
+                       *cb |= TEMIC_SET_PAL_L;
 
                }
                break;
 
        case TUNER_PHILIPS_FQ1216ME:
-               cb &= ~0x0f;
+               *cb &= ~0x0f;
 
                if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
-                       cb |= PHILIPS_SET_PAL_BGDK;
+                       *cb |= PHILIPS_SET_PAL_BGDK;
 
                } else if (params->std & V4L2_STD_PAL_I) {
-                       cb |= PHILIPS_SET_PAL_I;
+                       *cb |= PHILIPS_SET_PAL_I;
 
                } else if (params->std & V4L2_STD_SECAM_L) {
-                       cb |= PHILIPS_SET_PAL_L;
+                       *cb |= PHILIPS_SET_PAL_L;
 
                }
                break;
 
-       case TUNER_PHILIPS_ATSC:
+       case TUNER_PHILIPS_FCV1236D:
                /* 0x00 -> ATSC antenna input 1 */
                /* 0x01 -> ATSC antenna input 2 */
                /* 0x02 -> NTSC antenna input 1 */
                /* 0x03 -> NTSC antenna input 2 */
-               cb &= ~0x03;
+               *cb &= ~0x03;
                if (!(params->std & V4L2_STD_ATSC))
-                       cb |= 2;
-               /* FIXME: input */
+                       *cb |= 2;
                break;
 
        case TUNER_MICROTUNE_4042FI5:
                /* Set the charge pump for fast tuning */
-               config |= TUNER_CHARGE_PUMP;
+               *config |= TUNER_CHARGE_PUMP;
                break;
 
        case TUNER_PHILIPS_TUV1236D:
+       {
                /* 0x40 -> ATSC antenna input 1 */
                /* 0x48 -> ATSC antenna input 2 */
                /* 0x00 -> NTSC antenna input 1 */
                /* 0x08 -> NTSC antenna input 2 */
-               buffer[0] = 0x14;
-               buffer[1] = 0x00;
-               buffer[2] = 0x17;
-               buffer[3] = 0x00;
-               cb &= ~0x40;
+               u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
+               *cb &= ~0x40;
                if (params->std & V4L2_STD_ATSC) {
-                       cb |= 0x40;
+                       *cb |= 0x40;
                        buffer[1] = 0x04;
                }
                /* set to the correct mode (analog or digital) */
                tuneraddr = priv->i2c_props.addr;
                priv->i2c_props.addr = 0x0a;
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
                priv->i2c_props.addr = tuneraddr;
-               /* FIXME: input */
                break;
        }
+       }
+       if (atv_input[priv->nr])
+               simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
+
+       return 0;
+}
+
+static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
+                           u16 div, u8 config, u8 cb)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       int rc;
+
+       switch (priv->type) {
+       case TUNER_LG_TDVS_H06XF:
+               /* Set the Auxiliary Byte. */
+               buffer[0] = buffer[2];
+               buffer[0] &= ~0x20;
+               buffer[0] |= 0x18;
+               buffer[1] = 0x20;
+               tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
+               if (2 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 2)\n", rc);
+               break;
+       case TUNER_MICROTUNE_4042FI5:
+       {
+               /* FIXME - this may also work for other tuners */
+               unsigned long timeout = jiffies + msecs_to_jiffies(1);
+               u8 status_byte = 0;
+
+               /* Wait until the PLL locks */
+               for (;;) {
+                       if (time_after(jiffies, timeout))
+                               return 0;
+                       rc = tuner_i2c_xfer_recv(&priv->i2c_props,
+                                                &status_byte, 1);
+                       if (1 != rc) {
+                               tuner_warn("i2c i/o read error: rc == %d "
+                                          "(should be 1)\n", rc);
+                               break;
+                       }
+                       if (status_byte & TUNER_PLL_LOCKED)
+                               break;
+                       udelay(10);
+               }
+
+               /* Set the charge pump for optimized phase noise figure */
+               config &= ~TUNER_CHARGE_PUMP;
+               buffer[0] = (div>>8) & 0x7f;
+               buffer[1] = div      & 0xff;
+               buffer[2] = config;
+               buffer[3] = cb;
+               tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+                         buffer[0], buffer[1], buffer[2], buffer[3]);
+
+               rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+               if (4 != rc)
+                       tuner_warn("i2c i/o error: rc == %d "
+                                  "(should be 4)\n", rc);
+               break;
+       }
+       }
+
+       return 0;
+}
+
+static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       switch (priv->type) {
+       case TUNER_TENA_9533_DI:
+       case TUNER_YMEC_TVF_5533MF:
+               tuner_dbg("This tuner doesn't have FM. "
+                         "Most cards have a TEA5767 for FM\n");
+               return 0;
+       case TUNER_PHILIPS_FM1216ME_MK3:
+       case TUNER_PHILIPS_FM1236_MK3:
+       case TUNER_PHILIPS_FMD1216ME_MK3:
+       case TUNER_LG_NTSC_TAPE:
+       case TUNER_PHILIPS_FM1256_IH3:
+               buffer[3] = 0x19;
+               break;
+       case TUNER_TNF_5335MF:
+               buffer[3] = 0x11;
+               break;
+       case TUNER_LG_PAL_FM:
+               buffer[3] = 0xa5;
+               break;
+       case TUNER_THOMSON_DTT761X:
+               buffer[3] = 0x39;
+               break;
+       case TUNER_MICROTUNE_4049FM5:
+       default:
+               buffer[3] = 0xa4;
+               break;
+       }
+
+       return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int simple_set_tv_freq(struct dvb_frontend *fe,
+                             struct analog_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u8 config, cb;
+       u16 div;
+       struct tunertype *tun;
+       u8 buffer[4];
+       int rc, IFPCoff, i;
+       enum param_type desired_type;
+       struct tuner_params *t_params;
+
+       tun = priv->tun;
+
+       /* IFPCoff = Video Intermediate Frequency - Vif:
+               940  =16*58.75  NTSC/J (Japan)
+               732  =16*45.75  M/N STD
+               704  =16*44     ATSC (at DVB code)
+               632  =16*39.50  I U.K.
+               622.4=16*38.90  B/G D/K I, L STD
+               592  =16*37.00  D China
+               590  =16.36.875 B Australia
+               543.2=16*33.95  L' STD
+               171.2=16*10.70  FM Radio (at set_radio_freq)
+       */
+
+       if (params->std == V4L2_STD_NTSC_M_JP) {
+               IFPCoff      = 940;
+               desired_type = TUNER_PARAM_TYPE_NTSC;
+       } else if ((params->std & V4L2_STD_MN) &&
+                 !(params->std & ~V4L2_STD_MN)) {
+               IFPCoff      = 732;
+               desired_type = TUNER_PARAM_TYPE_NTSC;
+       } else if (params->std == V4L2_STD_SECAM_LC) {
+               IFPCoff      = 543;
+               desired_type = TUNER_PARAM_TYPE_SECAM;
+       } else {
+               IFPCoff      = 623;
+               desired_type = TUNER_PARAM_TYPE_PAL;
+       }
+
+       t_params = simple_tuner_params(fe, desired_type);
+
+       i = simple_config_lookup(fe, t_params, &params->frequency,
+                                &config, &cb);
+
+       div = params->frequency + IFPCoff + offset;
+
+       tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
+                 "Offset=%d.%02d MHz, div=%0d\n",
+                 params->frequency / 16, params->frequency % 16 * 100 / 16,
+                 IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+                 offset / 16, offset % 16 * 100 / 16, div);
+
+       /* tv norm specific stuff for multi-norm tuners */
+       simple_std_setup(fe, params, &config, &cb);
 
        if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
                buffer[0] = config;
@@ -357,8 +588,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
        if (t_params->has_tda9887) {
                struct v4l2_priv_tun_config tda9887_cfg;
                int config = 0;
-               int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
-                       !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
+               int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
+                                                V4L2_STD_SECAM_LC)) &&
+                       !(params->std & ~(V4L2_STD_SECAM_L |
+                                         V4L2_STD_SECAM_LC));
 
                tda9887_cfg.tuner = TUNER_TDA9887;
                tda9887_cfg.priv  = &config;
@@ -368,8 +601,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
                                config |= TDA9887_PORT2_ACTIVE;
-               }
-               else {
+               } else {
                        if (t_params->port1_active)
                                config |= TDA9887_PORT1_ACTIVE;
                        if (t_params->port2_active)
@@ -384,8 +616,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                config |= TDA9887_TOP(t_params->default_top_secam_mid);
                        else if (t_params->default_top_secam_high)
                                config |= TDA9887_TOP(t_params->default_top_secam_high);
-               }
-               else {
+               } else {
                        if (i == 0 && t_params->default_top_low)
                                config |= TDA9887_TOP(t_params->default_top_low);
                        else if (i == 1 && t_params->default_top_mid)
@@ -399,56 +630,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
                                    &tda9887_cfg);
        }
        tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                 buffer[0],buffer[1],buffer[2],buffer[3]);
-
-       if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-               tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
-
-       switch (priv->type) {
-       case TUNER_LG_TDVS_H06XF:
-               /* Set the Auxiliary Byte. */
-               buffer[0] = buffer[2];
-               buffer[0] &= ~0x20;
-               buffer[0] |= 0x18;
-               buffer[1] = 0x20;
-               tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
-
-               if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
-               break;
-       case TUNER_MICROTUNE_4042FI5:
-       {
-               // FIXME - this may also work for other tuners
-               unsigned long timeout = jiffies + msecs_to_jiffies(1);
-               u8 status_byte = 0;
+                 buffer[0], buffer[1], buffer[2], buffer[3]);
 
-               /* Wait until the PLL locks */
-               for (;;) {
-                       if (time_after(jiffies,timeout))
-                               return 0;
-                       if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {
-                               tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
-                               break;
-                       }
-                       if (status_byte & TUNER_PLL_LOCKED)
-                               break;
-                       udelay(10);
-               }
+       rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+       if (4 != rc)
+               tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
 
-               /* Set the charge pump for optimized phase noise figure */
-               config &= ~TUNER_CHARGE_PUMP;
-               buffer[0] = (div>>8) & 0x7f;
-               buffer[1] = div      & 0xff;
-               buffer[2] = config;
-               buffer[3] = cb;
-               tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                         buffer[0],buffer[1],buffer[2],buffer[3]);
+       simple_post_tune(fe, &buffer[0], div, config, cb);
 
-               if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-                       tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
-               break;
-       }
-       }
        return 0;
 }
 
@@ -483,37 +672,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                freq += (unsigned int)(41.3*16000);
                break;
        default:
-               tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);
+               tuner_warn("Unsupported radio_if value %d\n",
+                          t_params->radio_if);
                return 0;
        }
 
        /* Bandswitch byte */
-       switch (priv->type) {
-       case TUNER_TENA_9533_DI:
-       case TUNER_YMEC_TVF_5533MF:
-               tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
-               return 0;
-       case TUNER_PHILIPS_FM1216ME_MK3:
-       case TUNER_PHILIPS_FM1236_MK3:
-       case TUNER_PHILIPS_FMD1216ME_MK3:
-       case TUNER_LG_NTSC_TAPE:
-       case TUNER_PHILIPS_FM1256_IH3:
-               buffer[3] = 0x19;
-               break;
-       case TUNER_TNF_5335MF:
-               buffer[3] = 0x11;
-               break;
-       case TUNER_LG_PAL_FM:
-               buffer[3] = 0xa5;
-               break;
-       case TUNER_THOMSON_DTT761X:
-               buffer[3] = 0x39;
-               break;
-       case TUNER_MICROTUNE_4049FM5:
-       default:
-               buffer[3] = 0xa4;
-               break;
-       }
+       simple_radio_bandswitch(fe, &buffer[0]);
 
        buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
                    TUNER_RATIO_SELECT_50; /* 50 kHz step */
@@ -534,7 +699,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
        }
 
        tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
-              buffer[0],buffer[1],buffer[2],buffer[3]);
+              buffer[0], buffer[1], buffer[2], buffer[3]);
        priv->last_div = div;
 
        if (t_params->has_tda9887) {
@@ -544,9 +709,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                tda9887_cfg.tuner = TUNER_TDA9887;
                tda9887_cfg.priv = &config;
 
-               if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)
+               if (t_params->port1_active &&
+                   !t_params->port1_fm_high_sensitivity)
                        config |= TDA9887_PORT1_ACTIVE;
-               if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)
+               if (t_params->port2_active &&
+                   !t_params->port2_fm_high_sensitivity)
                        config |= TDA9887_PORT2_ACTIVE;
                if (t_params->intercarrier_mode)
                        config |= TDA9887_INTERCARRIER;
@@ -557,10 +724,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
                if (t_params->radio_if == 2)
                        config |= TDA9887_RIF_41_3;
                i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
-                                       &tda9887_cfg);
+                                   &tda9887_cfg);
        }
-       if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
-               tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+       rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+       if (4 != rc)
+               tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
 
        return 0;
 }
@@ -571,6 +739,9 @@ static int simple_set_params(struct dvb_frontend *fe,
        struct tuner_simple_priv *priv = fe->tuner_priv;
        int ret = -EINVAL;
 
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
        switch (params->mode) {
        case V4L2_TUNER_RADIO:
                ret = simple_set_radio_freq(fe, params);
@@ -582,14 +753,210 @@ static int simple_set_params(struct dvb_frontend *fe,
                priv->frequency = params->frequency * 62500;
                break;
        }
+       priv->bandwidth = 0;
 
        return ret;
 }
 
+static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
+                          const struct dvb_frontend_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       switch (priv->type) {
+       case TUNER_PHILIPS_FMD1216ME_MK3:
+               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
+                   params->frequency >= 158870000)
+                       buf[3] |= 0x08;
+               break;
+       case TUNER_PHILIPS_TD1316:
+               /* determine band */
+               buf[3] |= (params->frequency < 161000000) ? 1 :
+                         (params->frequency < 444000000) ? 2 : 4;
+
+               /* setup PLL filter */
+               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+                       buf[3] |= 1 << 3;
+               break;
+       case TUNER_PHILIPS_TUV1236D:
+       case TUNER_PHILIPS_FCV1236D:
+       {
+               unsigned int new_rf;
+
+               if (dtv_input[priv->nr])
+                       new_rf = dtv_input[priv->nr];
+               else
+                       switch (params->u.vsb.modulation) {
+                       case QAM_64:
+                       case QAM_256:
+                               new_rf = 1;
+                               break;
+                       case VSB_8:
+                       default:
+                               new_rf = 0;
+                               break;
+                       }
+               simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
+                               const struct dvb_frontend_parameters *params)
+{
+       /* This function returns the tuned frequency on success, 0 on error */
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       struct tunertype *tun = priv->tun;
+       static struct tuner_params *t_params;
+       u8 config, cb;
+       u32 div;
+       int ret, frequency = params->frequency / 62500;
+
+       t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
+       ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
+       if (ret < 0)
+               return 0; /* failure */
+
+       div = ((frequency + t_params->iffreq) * 62500 + offset +
+              tun->stepsize/2) / tun->stepsize;
+
+       buf[0] = div >> 8;
+       buf[1] = div & 0xff;
+       buf[2] = config;
+       buf[3] = cb;
+
+       simple_set_dvb(fe, buf, params);
+
+       tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
+                 tun->name, div, buf[0], buf[1], buf[2], buf[3]);
+
+       /* calculate the frequency we set it to */
+       return (div * tun->stepsize) - t_params->iffreq;
+}
+
+static int simple_dvb_calc_regs(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params,
+                               u8 *buf, int buf_len)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u32 frequency;
+
+       if (buf_len < 5)
+               return -EINVAL;
+
+       frequency = simple_dvb_configure(fe, buf+1, params);
+       if (frequency == 0)
+               return -EINVAL;
+
+       buf[0] = priv->i2c_props.addr;
+
+       priv->frequency = frequency;
+       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+               params->u.ofdm.bandwidth : 0;
+
+       return 5;
+}
+
+static int simple_dvb_set_params(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *params)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       u32 prev_freq, prev_bw;
+       int ret;
+       u8 buf[5];
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       prev_freq = priv->frequency;
+       prev_bw   = priv->bandwidth;
+
+       ret = simple_dvb_calc_regs(fe, params, buf, 5);
+       if (ret != 5)
+               goto fail;
+
+       /* put analog demod in standby when tuning digital */
+       if (fe->ops.analog_ops.standby)
+               fe->ops.analog_ops.standby(fe);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* buf[0] contains the i2c address, but *
+        * we already have it in i2c_props.addr */
+       ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
+       if (ret != 4)
+               goto fail;
+
+       return 0;
+fail:
+       /* calc_regs sets frequency and bandwidth. if we failed, unset them */
+       priv->frequency = prev_freq;
+       priv->bandwidth = prev_bw;
+
+       return ret;
+}
+
+static int simple_init(struct dvb_frontend *fe)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       if (priv->tun->initdata) {
+               int ret;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = tuner_i2c_xfer_send(&priv->i2c_props,
+                                         priv->tun->initdata + 1,
+                                         priv->tun->initdata[0]);
+               if (ret != priv->tun->initdata[0])
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int simple_sleep(struct dvb_frontend *fe)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       if (priv->tun->sleepdata) {
+               int ret;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = tuner_i2c_xfer_send(&priv->i2c_props,
+                                         priv->tun->sleepdata + 1,
+                                         priv->tun->sleepdata[0]);
+               if (ret != priv->tun->sleepdata[0])
+                       return ret;
+       }
+
+       return 0;
+}
 
 static int simple_release(struct dvb_frontend *fe)
 {
-       kfree(fe->tuner_priv);
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+
+       mutex_lock(&tuner_simple_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&tuner_simple_list_mutex);
+
        fe->tuner_priv = NULL;
 
        return 0;
@@ -602,10 +969,22 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
+static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct tuner_simple_priv *priv = fe->tuner_priv;
+       *bandwidth = priv->bandwidth;
+       return 0;
+}
+
 static struct dvb_tuner_ops simple_tuner_ops = {
+       .init              = simple_init,
+       .sleep             = simple_sleep,
        .set_analog_params = simple_set_params,
+       .set_params        = simple_dvb_set_params,
+       .calc_regs         = simple_dvb_calc_regs,
        .release           = simple_release,
        .get_frequency     = simple_get_frequency,
+       .get_bandwidth     = simple_get_bandwidth,
        .get_status        = simple_get_status,
        .get_rf_strength   = simple_get_rf_strength,
 };
@@ -613,30 +992,92 @@ static struct dvb_tuner_ops simple_tuner_ops = {
 struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                         struct i2c_adapter *i2c_adap,
                                         u8 i2c_addr,
-                                        struct simple_tuner_config *cfg)
+                                        unsigned int type)
 {
        struct tuner_simple_priv *priv = NULL;
+       int instance;
 
-       priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);
-       if (priv == NULL)
+       if (type >= tuner_count) {
+               printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
+                      __func__, type, tuner_count-1);
                return NULL;
-       fe->tuner_priv = priv;
+       }
 
-       priv->i2c_props.addr = i2c_addr;
-       priv->i2c_props.adap = i2c_adap;
-       priv->type = cfg->type;
-       priv->tun  = cfg->tun;
+       /* If i2c_adap is set, check that the tuner is at the correct address.
+        * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
+        * by the digital demod via calc_regs.
+        */
+       if (i2c_adap != NULL) {
+               u8 b[1];
+               struct i2c_msg msg = {
+                       .addr = i2c_addr, .flags = I2C_M_RD,
+                       .buf = b, .len = 1,
+               };
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               if (1 != i2c_transfer(i2c_adap, &msg, 1))
+                       tuner_warn("unable to probe %s, proceeding anyway.",
+                                  tuners[type].name);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
-       memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));
+       mutex_lock(&tuner_simple_list_mutex);
 
-       tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);
+       instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c_adap, i2c_addr,
+                                             "tuner-simple");
+       switch (instance) {
+       case 0:
+               mutex_unlock(&tuner_simple_list_mutex);
+               return NULL;
+               break;
+       case 1:
+               fe->tuner_priv = priv;
 
-       strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));
+               priv->type = type;
+               priv->tun  = &tuners[type];
+               priv->nr   = simple_devcount++;
+               break;
+       default:
+               fe->tuner_priv = priv;
+               break;
+       }
 
-       return fe;
-}
+       mutex_unlock(&tuner_simple_list_mutex);
+
+       memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+
+       if ((debug) || ((atv_input[priv->nr] > 0) ||
+                       (dtv_input[priv->nr] > 0))) {
+               if (0 == atv_input[priv->nr])
+                       tuner_info("tuner %d atv rf input will be "
+                                  "autoselected\n", priv->nr);
+               else
+                       tuner_info("tuner %d atv rf input will be "
+                                  "set to input %d (insmod option)\n",
+                                  priv->nr, atv_input[priv->nr]);
+               if (0 == dtv_input[priv->nr])
+                       tuner_info("tuner %d dtv rf input will be "
+                                  "autoselected\n", priv->nr);
+               else
+                       tuner_info("tuner %d dtv rf input will be "
+                                  "set to input %d (insmod option)\n",
+                                  priv->nr, dtv_input[priv->nr]);
+       }
 
+       strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
+               sizeof(fe->ops.tuner_ops.info.name));
 
+       return fe;
+}
 EXPORT_SYMBOL_GPL(simple_tuner_attach);
 
 MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
index 9089939a8c0214e9b71c177f7880936efd14edb5..e46cf0121e030a23e314190116567550f9c7ff7e 100644 (file)
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-struct simple_tuner_config
-{
-       /* chip type */
-       unsigned int type;
-       struct tunertype *tun;
-};
-
 #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
 extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                struct i2c_adapter *i2c_adap,
                                                u8 i2c_addr,
-                                               struct simple_tuner_config *cfg);
+                                               unsigned int type);
 #else
 static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                       struct i2c_adapter *i2c_adap,
                                                       u8 i2c_addr,
-                                                      struct simple_tuner_config *cfg)
+                                                      unsigned int type)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
index 883047f9c28c32f66eb7c98a5b080dcf92bc6e06..10dddca8b5d1817ede0be39bab500c2841c5ea4e 100644 (file)
  *     based on the video standard in use.
  */
 
+/* The following was taken from dvb-pll.c: */
+
+/* Set AGC TOP value to 103 dBuV:
+ *     0x80 = Control Byte
+ *     0x40 = 250 uA charge pump (irrelevant)
+ *     0x18 = Aux Byte to follow
+ *     0x06 = 64.5 kHz divider (irrelevant)
+ *     0x01 = Disable Vt (aka sleep)
+ *
+ *     0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
+ *     0x50 = AGC Take over point = 103 dBuV
+ */
+static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
+
+/*     0x04 = 166.67 kHz divider
+ *
+ *     0x80 = AGC Time constant 50ms Iagc = 9 uA
+ *     0x20 = AGC Take over point = 112 dBuV
+ */
+static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
+
 /* 0-9 */
 /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
 
@@ -594,19 +615,31 @@ static struct tuner_params tuner_philips_pal_mk_params[] = {
        },
 };
 
-/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */
+/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
 
-static struct tuner_range tuner_philips_fcv1236d_ranges[] = {
-       { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
-       { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
+static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
+       { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
+       { 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
+       { 16 * 999.99        , 0x8e, 0x32, },
+};
+
+static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
+       { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
+       { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
        { 16 * 999.99        , 0x8e, 0x30, },
 };
 
 static struct tuner_params tuner_philips_fcv1236d_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_NTSC,
-               .ranges = tuner_philips_fcv1236d_ranges,
-               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_ranges),
+               .ranges = tuner_philips_fcv1236d_ntsc_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
+       },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_fcv1236d_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
+               .iffreq = 16 * 44.00,
        },
 };
 
@@ -701,12 +734,24 @@ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x31, },
 };
 
+static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
+       { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
+       { 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
+       { 16 * 999.99        , 0x8e, 0x31, },
+};
+
 static struct tuner_params tuner_microtune_4042fi5_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_NTSC,
                .ranges = tuner_microtune_4042fi5_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_microtune_4042fi5_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
+               .iffreq = 16 * 44.00 /*MHz*/,
+       },
 };
 
 /* 50-59 */
@@ -740,6 +785,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
 
 /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
 
+/* single range used for both ntsc and atsc */
 static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
        { 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
        { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
@@ -752,6 +798,12 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = {
                .ranges = tuner_thomson_dtt7610_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+               .iffreq = 16 * 44.00 /*MHz*/,
+       },
 };
 
 /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
@@ -855,6 +907,11 @@ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x3c, },
 };
 
+static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
+       { 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
+       { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
+       { 16 * 999.99        , 0x8e, 0x3c, },
+};
 
 static struct tuner_params tuner_thomson_dtt761x_params[] = {
        {
@@ -865,6 +922,12 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
                .fm_gain_normal = 1,
                .radio_if = 2, /* 41.3 MHz */
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_dtt761x_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
+               .iffreq = 16 * 44.00, /*MHz*/
+       },
 };
 
 /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
@@ -891,6 +954,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
        { 16 * 999.99        , 0x86, 0x54, },
 };
 
+static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
+       { 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
+       { 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
+       { 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
+       { 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
+       { 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
+       { 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
+       { 16 * 999.99        , 0xfc, 0x44 },
+};
 
 static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
        {
@@ -904,6 +976,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
                .port2_invert_for_secam_lc = 1,
                .port1_set_for_fm_mono = 1,
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
+               .iffreq = 16 * 36.125, /*MHz*/
+       },
 };
 
 
@@ -915,6 +993,11 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
        { 16 * 999.99        , 0x8e, 0x04 },
 };
 
+static struct tuner_range tuner_tua6034_atsc_ranges[] = {
+       { 16 * 165.00 /*MHz*/, 0xce, 0x01 },
+       { 16 * 450.00 /*MHz*/, 0xce, 0x02 },
+       { 16 * 999.99        , 0xce, 0x04 },
+};
 
 static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
        {
@@ -922,6 +1005,12 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
                .ranges = tuner_tua6034_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_tua6034_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
+               .iffreq = 16 * 44.00,
+       },
 };
 
 /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
@@ -974,12 +1063,30 @@ static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
        { 16 * 999.99        , 0xc8, 0xa4, },
 };
 
+static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
+       { 16 *  93.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
+       { 16 * 253.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
+       { 16 * 583.834 /*MHz*/, 0xca, 0x60, },
+       { 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
+       { 16 * 999.999        , 0xca, 0xe0, },
+};
+
 static struct tuner_params tuner_philips_td1316_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_PAL,
                .ranges = tuner_philips_td1316_pal_ranges,
                .count  = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_philips_td1316_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
+               .iffreq = 16 * 36.166667 /*MHz*/,
+       },
 };
 
 /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
@@ -990,6 +1097,11 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
        { 16 * 999.99        , 0xce, 0x04, },
 };
 
+static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
+       { 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
+       { 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
+       { 16 * 999.99        , 0xc6, 0x44, },
+};
 
 static struct tuner_params tuner_tuv1236d_params[] = {
        {
@@ -997,6 +1109,12 @@ static struct tuner_params tuner_tuv1236d_params[] = {
                .ranges = tuner_tuv1236d_ntsc_ranges,
                .count  = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
        },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_tuv1236d_atsc_ranges,
+               .count  = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
+               .iffreq = 16 * 44.00,
+       },
 };
 
 /* ------------ TUNER_TNF_xxx5  - Texas Instruments--------- */
@@ -1050,17 +1168,30 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
 
 /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
 
-static struct tuner_range tuner_thomson_fe6600_ranges[] = {
+static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
        { 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
        { 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
        { 16 * 999.99        , 0xf6, 0x18, },
 };
 
+static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
+       { 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
+       { 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
+       { 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
+       { 16 * 999.99        , 0xf4, 0x18, },
+};
+
 static struct tuner_params tuner_thomson_fe6600_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_PAL,
-               .ranges = tuner_thomson_fe6600_ranges,
-               .count  = ARRAY_SIZE(tuner_thomson_fe6600_ranges),
+               .ranges = tuner_thomson_fe6600_pal_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
+       },
+       {
+               .type   = TUNER_PARAM_TYPE_DIGITAL,
+               .ranges = tuner_thomson_fe6600_dvb_ranges,
+               .count  = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
+               .iffreq = 16 * 36.125 /*MHz*/,
        },
 };
 
@@ -1303,10 +1434,13 @@ struct tunertype tuners[] = {
                .params = tuner_philips_pal_mk_params,
                .count  = ARRAY_SIZE(tuner_philips_pal_mk_params),
        },
-       [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+       [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
                .name   = "Philips FCV1236D ATSC/NTSC dual in",
                .params = tuner_philips_fcv1236d_params,
                .count  = ARRAY_SIZE(tuner_philips_fcv1236d_params),
+               .min = 16 *  53.00,
+               .max = 16 * 803.00,
+               .stepsize = 62500,
        },
        [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
                .name   = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
@@ -1342,6 +1476,9 @@ struct tunertype tuners[] = {
                .name   = "Microtune 4042 FI5 ATSC/NTSC dual in",
                .params = tuner_microtune_4042fi5_params,
                .count  = ARRAY_SIZE(tuner_microtune_4042fi5_params),
+               .min    = 16 *  57.00,
+               .max    = 16 * 858.00,
+               .stepsize = 62500,
        },
 
        /* 50-59 */
@@ -1359,6 +1496,9 @@ struct tunertype tuners[] = {
                .name   = "Thomson DTT 7610 (ATSC/NTSC)",
                .params = tuner_thomson_dtt7610_params,
                .count  = ARRAY_SIZE(tuner_thomson_dtt7610_params),
+               .min    = 16 *  44.00,
+               .max    = 16 * 958.00,
+               .stepsize = 62500,
        },
        [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
                .name   = "Philips FQ1286",
@@ -1400,6 +1540,10 @@ struct tunertype tuners[] = {
                .name   = "Thomson DTT 761X (ATSC/NTSC)",
                .params = tuner_thomson_dtt761x_params,
                .count  = ARRAY_SIZE(tuner_thomson_dtt761x_params),
+               .min    = 16 *  57.00,
+               .max    = 16 * 863.00,
+               .stepsize = 62500,
+               .initdata = tua603x_agc103,
        },
        [TUNER_TENA_9533_DI] = { /* Philips PAL */
                .name   = "Tena TNF9533-D/IF/TNF9533-B/DF",
@@ -1414,11 +1558,20 @@ struct tunertype tuners[] = {
                .name   = "Philips FMD1216ME MK3 Hybrid Tuner",
                .params = tuner_philips_fmd1216me_mk3_params,
                .count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
+               .min = 16 *  50.87,
+               .max = 16 * 858.00,
+               .stepsize = 166667,
+               .initdata = tua603x_agc112,
+               .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
        },
        [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
                .name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
                .params = tuner_lg_tdvs_h06xf_params,
                .count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
+               .min    = 16 *  54.00,
+               .max    = 16 * 863.00,
+               .stepsize = 62500,
+               .initdata = tua603x_agc103,
        },
        [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
                .name   = "Ymec TVF66T5-B/DFF",
@@ -1434,11 +1587,17 @@ struct tunertype tuners[] = {
                .name   = "Philips TD1316 Hybrid Tuner",
                .params = tuner_philips_td1316_params,
                .count  = ARRAY_SIZE(tuner_philips_td1316_params),
+               .min    = 16 *  87.00,
+               .max    = 16 * 895.00,
+               .stepsize = 166667,
        },
        [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
                .name   = "Philips TUV1236D ATSC/NTSC dual in",
                .params = tuner_tuv1236d_params,
                .count  = ARRAY_SIZE(tuner_tuv1236d_params),
+               .min    = 16 *  54.00,
+               .max    = 16 * 864.00,
+               .stepsize = 62500,
        },
        [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
                .name   = "Tena TNF 5335 and similar models",
@@ -1460,6 +1619,9 @@ struct tunertype tuners[] = {
                .name   = "Thomson FE6600",
                .params = tuner_thomson_fe6600_params,
                .count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
+               .min    = 16 *  44.25,
+               .max    = 16 * 858.00,
+               .stepsize = 166667,
        },
        [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
                .name   = "Samsung TCPG 6121P30A",
@@ -1480,5 +1642,11 @@ struct tunertype tuners[] = {
                /* see xc5000.c for details */
        },
 };
+EXPORT_SYMBOL(tuners);
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
+EXPORT_SYMBOL(tuner_count);
+
+MODULE_DESCRIPTION("Simple tuner device type database");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
index d0057fbf0ec72e9569a92b30121961663e371e3a..74dc46a71f64555c07bb67be9ee09facf822ad41 100644 (file)
@@ -1,6 +1,9 @@
 /* tuner-xc2028_types
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This file includes internal tipes to be used inside tuner-xc2028.
+ * Shouldn't be included outside tuner-xc2028
+ *
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License v2
  */
 
 /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
        and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
        There are variants both with and without NOGD
+       Those firmwares produce better result with LCD displays
  */
 #define LCD            (1<<12)
 
 /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
        and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
+       The NOGD firmwares don't have group delay compensation filter
  */
 #define NOGD           (1<<13)
 
 /* This flag identifies that the scode table has a new format */
 #define HAS_IF         (1 << 30)
 
-#define SCODE_TYPES    (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
-                        LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794|     \
-                        DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
+/* There are different scode tables for MTS and non-MTS.
+   The MTS firmwares support mono only
+  */
+#define SCODE_TYPES (SCODE | MTS)
+
 
-/* Newer types to be moved to videodev2.h */
+/* Newer types not defined on videodev2.h.
+   The original idea were to move all those types to videodev2.h, but
+   it seemed overkill, since, with the exception of SECAM/K3, the other
+   types seem to be autodetected.
+   It is not clear where secam/k3 is used, nor we have a feedback of this
+   working or being autodetected by the standard secam firmware.
+ */
 
 #define V4L2_STD_SECAM_K3      (0x04000000)
 
index 50cf876f020f40659929821f5c560fb58b5b8cbf..cc3db7d79a0d195adc386205621f617ecbb57ac4 100644 (file)
@@ -1,6 +1,6 @@
 /* tuner-xc2028
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  *
  * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
  *       - frontend interface
@@ -23,8 +23,6 @@
 #include "dvb_frontend.h"
 
 
-#define PREFIX "xc2028"
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std,
        "NICAM/A\n"
        "NICAM/B\n");
 
+static char firmware_name[FIRMWARE_NAME_MAX];
+module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
+                               "default firmware name\n");
+
 static LIST_HEAD(xc2028_list);
 static DEFINE_MUTEX(xc2028_list_mutex);
 
@@ -127,12 +130,12 @@ struct xc2028_data {
        _rc;                                                            \
 })
 
-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
 {
        unsigned char buf[2];
        unsigned char ibuf[2];
 
-       tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
+       tuner_dbg("%s %04x called\n", __func__, reg);
 
        buf[0] = reg >> 8;
        buf[1] = (unsigned char) reg;
@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
 }
 
 #define dump_firm_type(t)      dump_firm_type_and_int_freq(t, 0)
-void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
 {
         if (type & BASE)
                printk("BASE ");
@@ -232,6 +235,7 @@ static  v4l2_std_id parse_audio_std_option(void)
 static void free_firmware(struct xc2028_data *priv)
 {
        int i;
+       tuner_dbg("%s called\n", __func__);
 
        if (!priv->firm)
                return;
@@ -255,19 +259,24 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        int                   rc = 0;
        int                   n, n_array;
        char                  name[33];
+       char                  *fname;
+
+       tuner_dbg("%s called\n", __func__);
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       if (!firmware_name[0])
+               fname = priv->ctrl.fname;
+       else
+               fname = firmware_name;
 
-       tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
-       rc = request_firmware(&fw, priv->ctrl.fname,
-                             &priv->i2c_props.adap->dev);
+       tuner_dbg("Reading firmware %s\n", fname);
+       rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
        if (rc < 0) {
                if (rc == -ENOENT)
                        tuner_err("Error: firmware %s not found.\n",
-                                  priv->ctrl.fname);
+                                  fname);
                else
                        tuner_err("Error %d while requesting firmware %s \n",
-                                  rc, priv->ctrl.fname);
+                                  rc, fname);
 
                return rc;
        }
@@ -276,7 +285,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
 
        if (fw->size < sizeof(name) - 1 + 2 + 2) {
                tuner_err("Error: firmware file %s has invalid size!\n",
-                         priv->ctrl.fname);
+                         fname);
                goto corrupt;
        }
 
@@ -291,7 +300,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        p += 2;
 
        tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
-                  n_array, priv->ctrl.fname, name,
+                  n_array, fname, name,
                   priv->firm_version >> 8, priv->firm_version & 0xff);
 
        priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
@@ -395,9 +404,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
 {
        struct xc2028_data *priv = fe->tuner_priv;
        int                 i, best_i = -1, best_nr_matches = 0;
-       unsigned int        ign_firm_type_mask = 0;
+       unsigned int        type_mask = 0;
 
-       tuner_dbg("%s called, want type=", __FUNCTION__);
+       tuner_dbg("%s called, want type=", __func__);
        if (debug) {
                dump_firm_type(type);
                printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -412,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
                *id = V4L2_STD_PAL;
 
        if (type & BASE)
-               type &= BASE_TYPES;
+               type_mask = BASE_TYPES;
        else if (type & SCODE) {
                type &= SCODE_TYPES;
-               ign_firm_type_mask = HAS_IF;
+               type_mask = SCODE_TYPES & ~HAS_IF;
        } else if (type & DTV_TYPES)
-               type &= DTV_TYPES;
+               type_mask = DTV_TYPES;
        else if (type & STD_SPECIFIC_TYPES)
-               type &= STD_SPECIFIC_TYPES;
+               type_mask = STD_SPECIFIC_TYPES;
+
+       type &= type_mask;
+
+       if (!type & SCODE)
+               type_mask = ~0;
 
        /* Seek for exact match */
        for (i = 0; i < priv->firm_size; i++) {
-               if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
+               if ((type == (priv->firm[i].type & type_mask)) &&
                    (*id == priv->firm[i].id))
                        goto found;
        }
@@ -433,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
                v4l2_std_id match_mask;
                int nr_matches;
 
-               if (type != (priv->firm[i].type & ~ign_firm_type_mask))
+               if (type != (priv->firm[i].type & type_mask))
                        continue;
 
                match_mask = *id & priv->firm[i].id;
@@ -483,7 +497,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p, *endp, buf[priv->ctrl.max_len];
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        pos = seek_firmware(fe, type, id);
        if (pos < 0)
@@ -586,7 +600,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!int_freq) {
                pos = seek_firmware(fe, type, id);
@@ -650,7 +664,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
        u16                        version, hwmodel;
        v4l2_std_id                std0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!priv->firm) {
                if (!priv->ctrl.fname) {
@@ -770,10 +784,10 @@ check_device:
                goto fail;
        }
 
-       tuner_info("Device is Xceive %d version %d.%d, "
-                  "firmware version %d.%d\n",
-                  hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
-                  (version & 0xf0) >> 4, version & 0xf);
+       tuner_dbg("Device is Xceive %d version %d.%d, "
+                 "firmware version %d.%d\n",
+                 hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+                 (version & 0xf0) >> 4, version & 0xf);
 
        /* Check firmware version against what we downloaded. */
        if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
@@ -824,27 +838,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
        u16                 frq_lock, signal = 0;
        int                 rc;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
        /* Sync Lock Indicator */
        rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
-       if (rc < 0 || frq_lock == 0)
+       if (rc < 0)
                goto ret;
 
-       /* Frequency is locked. Return signal quality */
+       /* Frequency is locked */
+       if (frq_lock == 1)
+               signal = 32768;
 
        /* Get SNR of the video signal */
        rc = xc2028_get_reg(priv, 0x0040, &signal);
        if (rc < 0)
-               signal = -frq_lock;
+               goto ret;
+
+       /* Use both frq_lock and signal to generate the result */
+       signal = signal || ((signal & 0x07) << 12);
 
 ret:
        mutex_unlock(&priv->lock);
 
        *strength = signal;
 
+       tuner_dbg("signal strength is %d\n", signal);
+
        return rc;
 }
 
@@ -861,7 +882,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        unsigned char      buf[4];
        u32                div, offset = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -906,9 +927,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        if (rc < 0)
                goto ret;
 
-       rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
-       if (rc < 0)
-               goto ret;
+       /* Return code shouldn't be checked.
+          The reset CLK is needed only with tm6000.
+          Driver should work fine even if this fails.
+        */
+       priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
 
        msleep(10);
 
@@ -942,7 +965,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
        struct xc2028_data *priv = fe->tuner_priv;
        unsigned int       type=0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (p->mode == V4L2_TUNER_RADIO) {
                type |= FM;
@@ -975,7 +998,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
        fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
        u16                demod = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (priv->ctrl.d2633)
                type |= D2633;
@@ -1040,33 +1063,12 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                                T_DIGITAL_TV, type, 0, demod);
 }
 
-static int xc2028_sleep(struct dvb_frontend *fe)
-{
-       struct xc2028_data *priv = fe->tuner_priv;
-       int rc = 0;
-
-       tuner_dbg("%s called\n", __FUNCTION__);
-
-       mutex_lock(&priv->lock);
-
-       if (priv->firm_version < 0x0202)
-               rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
-       else
-               rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
-
-       priv->cur_fw.type = 0;  /* need firmware reload */
-
-       mutex_unlock(&priv->lock);
-
-       return rc;
-}
-
 
 static int xc2028_dvb_release(struct dvb_frontend *fe)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&xc2028_list_mutex);
 
@@ -1091,7 +1093,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        *frequency = priv->frequency;
 
@@ -1104,25 +1106,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
        struct xc2028_ctrl *p    = priv_cfg;
        int                 rc   = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
-       kfree(priv->ctrl.fname);
-       free_firmware(priv);
-
        memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
-       priv->ctrl.fname = NULL;
+       if (priv->ctrl.max_len < 9)
+               priv->ctrl.max_len = 13;
 
        if (p->fname) {
+               if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
+                       kfree(priv->ctrl.fname);
+                       free_firmware(priv);
+               }
+
                priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
                if (priv->ctrl.fname == NULL)
                        rc = -ENOMEM;
        }
 
-       if (priv->ctrl.max_len < 9)
-               priv->ctrl.max_len = 13;
-
        mutex_unlock(&priv->lock);
 
        return rc;
@@ -1142,8 +1144,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
        .get_frequency     = xc2028_get_frequency,
        .get_rf_strength   = xc2028_signal,
        .set_params        = xc2028_set_params,
-       .sleep             = xc2028_sleep,
-
 };
 
 struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
@@ -1153,23 +1153,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        void               *video_dev;
 
        if (debug)
-               printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
+               printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
 
-       if (NULL == cfg || NULL == cfg->video_dev)
+       if (NULL == cfg)
                return NULL;
 
        if (!fe) {
-               printk(KERN_ERR PREFIX ": No frontend!\n");
+               printk(KERN_ERR "xc2028: No frontend!\n");
                return NULL;
        }
 
-       video_dev = cfg->video_dev;
+       video_dev = cfg->i2c_adap->algo_data;
+
+       if (debug)
+               printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
 
        mutex_lock(&xc2028_list_mutex);
 
        list_for_each_entry(priv, &xc2028_list, xc2028_list) {
-               if (priv->video_dev == cfg->video_dev) {
+               if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
                        video_dev = NULL;
+                       if (debug)
+                               printk(KERN_DEBUG "xc2028: reusing device\n");
+
                        break;
                }
        }
@@ -1183,6 +1189,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
 
                priv->i2c_props.addr = cfg->i2c_addr;
                priv->i2c_props.adap = cfg->i2c_adap;
+               priv->i2c_props.name = "xc2028";
+
                priv->video_dev = video_dev;
                priv->tuner_callback = cfg->callback;
                priv->ctrl.max_len = 13;
@@ -1195,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        fe->tuner_priv = priv;
        priv->count++;
 
+       if (debug)
+               printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+
        memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
               sizeof(xc2028_dvb_tuner_ops));
 
index 3eb8420379a42e29f108b65630082a7f1546366e..fc2f132a5541279e9c1b6089535dd42fd21fbb69 100644 (file)
@@ -1,6 +1,6 @@
 /* tuner-xc2028
  *
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License v2
  */
 
@@ -12,7 +12,7 @@
 #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
 
 /*      Dmoduler               IF (kHz) */
-#define        XC3028_FE_DEFAULT       0
+#define        XC3028_FE_DEFAULT       0               /* Don't load SCODE */
 #define XC3028_FE_LG60         6000
 #define        XC3028_FE_ATI638        6380
 #define        XC3028_FE_OREN538       5380
@@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
                                                 struct xc2028_config *cfg)
 {
        printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-              __FUNCTION__);
+              __func__);
        return NULL;
 }
 #endif
index 01ebcec040c4cee12cccb605085c1c3134ef3bfd..f29a2cd0f2f27c3db0afead3d5a7f65ba7f8fd56 100644 (file)
@@ -38,7 +38,7 @@
 /* ---------------------------------------------------------------------- */
 /* insmod args                                                            */
 
-static int debug = 0;  /* insmod parameter */
+static int debug;      /* insmod parameter */
 module_param(debug, int, 0644);
 
 MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
@@ -1235,11 +1235,11 @@ static int tda9850  = 1;
 static int tda9855  = 1;
 static int tda9873  = 1;
 static int tda9874a = 1;
-static int tea6300  = 0;  /* address clash with msp34xx */
-static int tea6320  = 0;  /* address clash with msp34xx */
+static int tea6300;    /* default 0 - address clash with msp34xx */
+static int tea6320;    /* default 0 - address clash with msp34xx */
 static int tea6420  = 1;
 static int pic16c54 = 1;
-static int ta8874z  = 0;  /* address clash with tda9840 */
+static int ta8874z;    /* default 0 - address clash with tda9840 */
 
 module_param(tda8425, int, 0444);
 module_param(tda9840, int, 0444);
index dc0da44a5af636a1b0ae4b053b91c74bd36ea3c4..3cf8a8e801e5eb0ec2649b020e9fdc931c6f0363 100644 (file)
@@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
 }
 EXPORT_SYMBOL(tveeprom_read);
 
-/* ----------------------------------------------------------------------- */
-/* needed for ivtv.sf.net at the moment.  Should go away in the long       */
-/* run, just call the exported tveeprom_* directly, there is no point in   */
-/* using the indirect way via i2c_driver->command()                        */
-
-static unsigned short normal_i2c[] = {
-       0xa0 >> 1,
-       I2C_CLIENT_END,
-};
-
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver i2c_driver_tveeprom;
-
-static int
-tveeprom_command(struct i2c_client *client,
-                unsigned int       cmd,
-                void              *arg)
-{
-       struct tveeprom eeprom;
-       u32 *eeprom_props = arg;
-       u8 *buf;
-
-       switch (cmd) {
-       case 0:
-               buf = kzalloc(256, GFP_KERNEL);
-               tveeprom_read(client, buf, 256);
-               tveeprom_hauppauge_analog(client, &eeprom, buf);
-               kfree(buf);
-               eeprom_props[0] = eeprom.tuner_type;
-               eeprom_props[1] = eeprom.tuner_formats;
-               eeprom_props[2] = eeprom.model;
-               eeprom_props[3] = eeprom.revision;
-               eeprom_props[4] = eeprom.has_radio;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int
-tveeprom_detect_client(struct i2c_adapter *adapter,
-                      int                 address,
-                      int                 kind)
-{
-       struct i2c_client *client;
-
-       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (NULL == client)
-               return -ENOMEM;
-       client->addr = address;
-       client->adapter = adapter;
-       client->driver = &i2c_driver_tveeprom;
-       snprintf(client->name, sizeof(client->name), "tveeprom");
-       i2c_attach_client(client);
-
-       return 0;
-}
-
-static int
-tveeprom_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (adapter->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
-       return 0;
-}
-
-static int
-tveeprom_detach_client(struct i2c_client *client)
-{
-       int err;
-
-       err = i2c_detach_client(client);
-       if (err < 0)
-               return err;
-       kfree(client);
-       return 0;
-}
-
-static struct i2c_driver i2c_driver_tveeprom = {
-       .driver = {
-               .name   = "tveeprom",
-       },
-       .id             = I2C_DRIVERID_TVEEPROM,
-       .attach_adapter = tveeprom_attach_adapter,
-       .detach_client  = tveeprom_detach_client,
-       .command        = tveeprom_command,
-};
-
-static int __init tveeprom_init(void)
-{
-       return i2c_add_driver(&i2c_driver_tveeprom);
-}
-
-static void __exit tveeprom_exit(void)
-{
-       i2c_del_driver(&i2c_driver_tveeprom);
-}
-
-module_init(tveeprom_init);
-module_exit(tveeprom_exit);
-
 /*
  * Local variables:
  * c-basic-offset: 8
index b6e24e714a230c1e53e212687dd97b1140cf0f22..6a3af1005f03e365f654e826890b7c1b8524474e 100644 (file)
@@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = {
 
 I2C_CLIENT_INSMOD;
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 14db95e10cfee6d8828b9d607b94369ffbf0f449..59166b760104884b4d0573e61572fd9b40b2ebcd 100644 (file)
@@ -121,7 +121,7 @@ static int init_model2_yb = -1;
 
 /* 01.01.08 - Added for RCA video in support -LO */
 /* Settings for camera model 3 */
-static int init_model3_input = 0;
+static int init_model3_input;
 
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
@@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
                return scan_Continue;
 }
 
+/*
+ * ibmcam_model3_parse_lines()
+ *
+ * | Even lines |     Odd Lines       |
+ * -----------------------------------|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |............|.....................|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |------------+---------------------|
+ *
+ * There is one (U, V) chroma pair for every four luma (Y) values.  This
+ * function reads a pair of lines at a time and obtains missing chroma values
+ * from adjacent pixels.
+ */
 static enum ParseState ibmcam_model3_parse_lines(
        struct uvd *uvd,
        struct usbvideo_frame *frame,
@@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines(
        const int ccm = 128; /* Color correction median - see below */
        int i, u, v, rw, data_w=0, data_h=0, color_corr;
        static unsigned char lineBuffer[640*3];
+       int line;
 
        color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
        RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
@@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines(
                return scan_NextFrame;
        }
 
-       /* Make sure there's enough data for the entire line */
-       len = 3 * data_w; /* <y-data> <uv-data> */
+       /* Make sure that lineBuffer can store two lines of data */
+       len = 3 * data_w; /* <y-data> <uyvy-data> */
        assert(len <= sizeof(lineBuffer));
 
-       /* Make sure there's enough data for the entire line */
+       /* Make sure there's enough data for two lines */
        if (RingQueue_GetLength(&uvd->dp) < len)
                return scan_Out;
 
-       /* Suck one line out of the ring queue */
+       /* Suck two lines of data out of the ring queue */
        RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
 
        data = lineBuffer;
@@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines(
        rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
        RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
 
-       for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-               int y, rv, gv, bv;      /* RGB components */
+       /* Iterate over two lines. */
+       for (line = 0; line < 2; line++) {
+               for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+                       int y;
+                       int rv, gv, bv; /* RGB components */
 
-               if (i < data_w) {
-                       y = data[i];    /* Luminosity is the first line */
+                       if (i >= data_w) {
+                               RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
+                               continue;
+                       }
+
+                       /* first line is YYY...Y; second is UYVY...UYVY */
+                       y = data[(line == 0) ? i : (i*2 + 1)];
 
                        /* Apply static color correction */
-                       u = color[i*2] + hue_corr;
-                       v = color[i*2 + 1] + hue2_corr;
+                       u = color[(i/2)*4] + hue_corr;
+                       v = color[(i/2)*4 + 2] + hue2_corr;
 
                        /* Apply color correction */
                        if (color_corr != 0) {
@@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines(
                                u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
                                v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
                        }
-               } else
-                       y = 0, u = v = 128;
 
-               YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-               RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
+
+                       YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+                       RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv);  /* No deinterlacing */
+               }
+
+               /* Check for the end of requested data */
+               if (rw == 0)
+                       break;
+
+               /* Prepare for the second line */
+               rw--;
+               data = lineBuffer + data_w;
        }
-       frame->deinterlace = Deinterlace_FillEvenLines;
+       frame->deinterlace = Deinterlace_None;
 
        /*
         * Account for number of bytes that we wrote into output V4L frame.
index 719b17ce83f832c87bf2ce50590af74d0a266bc0..1c180284ec6c2f35aa6fb3bd31e63ee97d562c0d 100644 (file)
@@ -57,11 +57,11 @@ static struct usbvideo *cams;
 static int debug;
 #define DEBUG(n, format, arg...) \
        if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
        }
 #else
 #define DEBUG(n, arg...)
-static const int debug = 0;
+static const int debug;
 #endif
 
 
index a2acba0bcc47586163bd4d82dffa91340354251b..32e536edf09d6cc594d4debb6c3f78c2082a1e42 100644 (file)
 static int debug;
 #define DEBUG(n, format, arg...) \
        if (n <= debug) {        \
-               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
        }
 #else
 #define DEBUG(n, arg...)
-static const int debug = 0;
+static const int debug;
 #endif
 
 #define DRIVER_VERSION "v0.01"
index 95453c108d40e650de7c1ddfb14bb8e59916f59b..9544e644bf0de4bc6f01b8e22107d20809683657 100644 (file)
@@ -28,9 +28,9 @@ typedef struct {
 
 static struct usbvideo *cams = NULL;
 
-static int debug = 0;
+static int debug;
 
-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
 
 static const int min_canvasWidth  = 8;
 static const int min_canvasHeight = 4;
index 5d363be7bc735762475576cb9e7dc6db43f04b80..4128ee20b64e3eee52db9e720b44d2f143a63f2b 100644 (file)
@@ -522,14 +522,14 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
        struct usbvideo_frame *frame;
        int num_cell = 0;
        int scan_length = 0;
-       static int num_pass = 0;
+       static int num_pass;
 
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return;
        }
        if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-               err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
+               err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
                return;
        }
 
@@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump);
 static int usbvideo_ClientIncModCount(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return -EINVAL;
        }
        if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __FUNCTION__);
+               err("%s: uvd->handle == NULL", __func__);
                return -EINVAL;
        }
        if (!try_module_get(uvd->handle->md_module)) {
-               err("%s: try_module_get() == 0", __FUNCTION__);
+               err("%s: try_module_get() == 0", __func__);
                return -ENODEV;
        }
        return 0;
@@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd)
 static void usbvideo_ClientDecModCount(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: uvd == NULL", __FUNCTION__);
+               err("%s: uvd == NULL", __func__);
                return;
        }
        if (uvd->handle == NULL) {
-               err("%s: uvd->handle == NULL", __FUNCTION__);
+               err("%s: uvd->handle == NULL", __func__);
                return;
        }
        if (uvd->handle->md_module == NULL) {
-               err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
+               err("%s: uvd->handle->md_module == NULL", __func__);
                return;
        }
        module_put(uvd->handle->md_module);
@@ -675,13 +675,13 @@ int usbvideo_register(
 
        /* Check parameters for sanity */
        if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
-               err("%s: Illegal call", __FUNCTION__);
+               err("%s: Illegal call", __func__);
                return -EINVAL;
        }
 
        /* Check registration callback - must be set! */
        if (cbTbl->probe == NULL) {
-               err("%s: probe() is required!", __FUNCTION__);
+               err("%s: probe() is required!", __func__);
                return -EINVAL;
        }
 
@@ -692,7 +692,7 @@ int usbvideo_register(
                return -ENOMEM;
        }
        dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
-           __FUNCTION__, cams, base_size, num_cams);
+           __func__, cams, base_size, num_cams);
 
        /* Copy callbacks, apply defaults for those that are not set */
        memmove(&cams->cb, cbTbl, sizeof(cams->cb));
@@ -721,7 +721,7 @@ int usbvideo_register(
                        up->user_data = kmalloc(up->user_size, GFP_KERNEL);
                        if (up->user_data == NULL) {
                                err("%s: Failed to allocate user_data (%d. bytes)",
-                                   __FUNCTION__, up->user_size);
+                                   __func__, up->user_size);
                                while (i) {
                                        up = &cams->cam[--i];
                                        kfree(up->user_data);
@@ -730,7 +730,7 @@ int usbvideo_register(
                                return -ENOMEM;
                        }
                        dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
-                            __FUNCTION__, i, up->user_data, up->user_size);
+                            __func__, i, up->user_data, up->user_size);
                }
        }
 
@@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams)
        int i;
 
        if (pCams == NULL) {
-               err("%s: pCams == NULL", __FUNCTION__);
+               err("%s: pCams == NULL", __func__);
                return;
        }
        cams = *pCams;
        if (cams == NULL) {
-               err("%s: cams == NULL", __FUNCTION__);
+               err("%s: cams == NULL", __func__);
                return;
        }
 
-       dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
+       dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
        usb_deregister(&cams->usbdrv);
 
-       dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
+       dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
        for (i=0; i < cams->num_cameras; i++) {
                struct uvd *up = &cams->cam[i];
                int warning = 0;
@@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams)
                }
                if (warning) {
                        err("%s: Warning: user_data=$%p user_size=%d.",
-                           __FUNCTION__, up->user_data, up->user_size);
+                           __func__, up->user_data, up->user_size);
                } else {
                        dbg("%s: Freeing %d. $%p->user_data=$%p",
-                           __FUNCTION__, i, up, up->user_data);
+                           __func__, i, up, up->user_data);
                        kfree(up->user_data);
                }
        }
        /* Whole array was allocated in one chunk */
        dbg("%s: Freed %d uvd structures",
-           __FUNCTION__, cams->num_cameras);
+           __func__, cams->num_cameras);
        kfree(cams);
        *pCams = NULL;
 }
@@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
        int i;
 
        if (uvd == NULL) {
-               err("%s($%p): Illegal call.", __FUNCTION__, intf);
+               err("%s($%p): Illegal call.", __func__, intf);
                return;
        }
 
@@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        usbvideo_ClientIncModCount(uvd);
        if (uvd->debug > 0)
-               info("%s(%p.)", __FUNCTION__, intf);
+               info("%s(%p.)", __func__, intf);
 
        mutex_lock(&uvd->lock);
        uvd->remove_pending = 1; /* Now all ISO data will be ignored */
@@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        video_unregister_device(&uvd->vdev);
        if (uvd->debug > 0)
-               info("%s: Video unregistered.", __FUNCTION__);
+               info("%s: Video unregistered.", __func__);
 
        if (uvd->user)
-               info("%s: In use, disconnect pending.", __FUNCTION__);
+               info("%s: In use, disconnect pending.", __func__);
        else
                usbvideo_CameraRelease(uvd);
        mutex_unlock(&uvd->lock);
@@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 static void usbvideo_CameraRelease(struct uvd *uvd)
 {
        if (uvd == NULL) {
-               err("%s: Illegal call", __FUNCTION__);
+               err("%s: Illegal call", __func__);
                return;
        }
 
@@ -946,7 +946,9 @@ static const struct file_operations usbvideo_fops = {
        .read =   usbvideo_v4l_read,
        .mmap =   usbvideo_v4l_mmap,
        .ioctl =  usbvideo_v4l_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek,
 };
 static const struct video_device usbvideo_template = {
@@ -1011,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
        char tmp1[20], tmp2[20];        /* Buffers for printing */
 
        if (uvd == NULL) {
-               err("%s: Illegal call.", __FUNCTION__);
+               err("%s: Illegal call.", __func__);
                return -EINVAL;
        }
        if (uvd->video_endp == 0) {
-               info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
+               info("%s: No video endpoint specified; data pump disabled.", __func__);
        }
        if (uvd->paletteBits == 0) {
-               err("%s: No palettes specified!", __FUNCTION__);
+               err("%s: No palettes specified!", __func__);
                return -EINVAL;
        }
        if (uvd->defaultPalette == 0) {
-               info("%s: No default palette!", __FUNCTION__);
+               info("%s: No default palette!", __func__);
        }
 
        uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
@@ -1032,19 +1034,19 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
 
        if (uvd->debug > 0) {
                info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
-                    __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+                    __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
        }
        if (uvd->dev == NULL) {
-               err("%s: uvd->dev == NULL", __FUNCTION__);
+               err("%s: uvd->dev == NULL", __func__);
                return -EINVAL;
        }
-       uvd->vdev.dev=&(uvd->dev->dev);
+       uvd->vdev.dev = &uvd->dev->dev;
        if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-               err("%s: video_register_device failed", __FUNCTION__);
+               err("%s: video_register_device failed", __func__);
                return -EPIPE;
        }
        if (uvd->debug > 1) {
-               info("%s: video_register_device() successful", __FUNCTION__);
+               info("%s: video_register_device() successful", __func__);
        }
 
        info("%s on /dev/video%d: canvas=%s videosize=%s",
@@ -1111,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        int i, errCode = 0;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, dev);
+               info("%s($%p)", __func__, dev);
 
        if (0 < usbvideo_ClientIncModCount(uvd))
                return -ENODEV;
        mutex_lock(&uvd->lock);
 
        if (uvd->user) {
-               err("%s: Someone tried to open an already opened device!", __FUNCTION__);
+               err("%s: Someone tried to open an already opened device!", __func__);
                errCode = -EBUSY;
        } else {
                /* Clear statistics */
@@ -1134,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
                RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
                if ((uvd->fbuf == NULL) ||
                    (!RingQueue_IsAllocated(&uvd->dp))) {
-                       err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
+                       err("%s: Failed to allocate fbuf or dp", __func__);
                        errCode = -ENOMEM;
                } else {
                        /* Allocate all buffers */
@@ -1178,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
                if (errCode == 0) {
                        if (VALID_CALLBACK(uvd, setupOnOpen)) {
                                if (uvd->debug > 1)
-                                       info("%s: setupOnOpen callback", __FUNCTION__);
+                                       info("%s: setupOnOpen callback", __func__);
                                errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
                                if (errCode < 0) {
                                        err("%s: setupOnOpen callback failed (%d.).",
-                                           __FUNCTION__, errCode);
+                                           __func__, errCode);
                                } else if (uvd->debug > 1) {
-                                       info("%s: setupOnOpen callback successful", __FUNCTION__);
+                                       info("%s: setupOnOpen callback successful", __func__);
                                }
                        }
                        if (errCode == 0) {
                                uvd->settingsAdjusted = 0;
                                if (uvd->debug > 1)
-                                       info("%s: Open succeeded.", __FUNCTION__);
+                                       info("%s: Open succeeded.", __func__);
                                uvd->user++;
                                file->private_data = uvd;
                        }
@@ -1200,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        if (errCode != 0)
                usbvideo_ClientDecModCount(uvd);
        if (uvd->debug > 0)
-               info("%s: Returning %d.", __FUNCTION__, errCode);
+               info("%s: Returning %d.", __func__, errCode);
        return errCode;
 }
 
@@ -1223,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        int i;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, dev);
+               info("%s($%p)", __func__, dev);
 
        mutex_lock(&uvd->lock);
        GET_CALLBACK(uvd, stopDataPump)(uvd);
@@ -1250,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        usbvideo_ClientDecModCount(uvd);
 
        if (uvd->debug > 1)
-               info("%s: Completed.", __FUNCTION__);
+               info("%s: Completed.", __func__);
        file->private_data = NULL;
        return 0;
 }
@@ -1504,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                return -EFAULT;
 
        if (uvd->debug >= 1)
-               info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
+               info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
 
        mutex_lock(&uvd->lock);
 
@@ -1551,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
         */
        if (frmx == -1) {
                if (uvd->defaultPalette == 0) {
-                       err("%s: No default palette; don't know what to do!", __FUNCTION__);
+                       err("%s: No default palette; don't know what to do!", __func__);
                        count = -EFAULT;
                        goto read_done;
                }
@@ -1623,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
        frame->seqRead_Index += count;
        if (uvd->debug >= 1) {
                err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
-                       __FUNCTION__, count, frame->seqRead_Index);
+                       __func__, count, frame->seqRead_Index);
        }
 
        /* Finally check if the frame is done with and "release" it */
@@ -1634,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                /* Mark it as available to be used again. */
                uvd->frame[frmx].frameState = FrameState_Unused;
                if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
-                       err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
+                       err("%s: usbvideo_NewFrame failed.", __func__);
                }
        }
 read_done:
@@ -1741,10 +1743,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        int i, errFlag;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, uvd);
+               info("%s($%p)", __func__, uvd);
 
        if (!CAMERA_IS_OPERATIONAL(uvd)) {
-               err("%s: Camera is not operational", __FUNCTION__);
+               err("%s: Camera is not operational", __func__);
                return -EFAULT;
        }
        uvd->curframe = -1;
@@ -1752,14 +1754,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        /* Alternate interface 1 is is the biggest frame size */
        i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
        if (i < 0) {
-               err("%s: usb_set_interface error", __FUNCTION__);
+               err("%s: usb_set_interface error", __func__);
                uvd->last_error = i;
                return -EBUSY;
        }
        if (VALID_CALLBACK(uvd, videoStart))
                GET_CALLBACK(uvd, videoStart)(uvd);
        else
-               err("%s: videoStart not set", __FUNCTION__);
+               err("%s: videoStart not set", __func__);
 
        /* We double buffer the Iso lists */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
@@ -1784,12 +1786,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
                if (errFlag)
-                       err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
+                       err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
        }
 
        uvd->streaming = 1;
        if (uvd->debug > 1)
-               info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
+               info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
        return 0;
 }
 
@@ -1811,14 +1813,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
                return;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __FUNCTION__, uvd);
+               info("%s($%p)", __func__, uvd);
 
        /* Unschedule all of the iso td's */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                usb_kill_urb(uvd->sbuf[i].urb);
        }
        if (uvd->debug > 1)
-               info("%s: streaming=0", __FUNCTION__);
+               info("%s: streaming=0", __func__);
        uvd->streaming = 0;
 
        if (!uvd->remove_pending) {
@@ -1826,12 +1828,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
                if (VALID_CALLBACK(uvd, videoStop))
                        GET_CALLBACK(uvd, videoStop)(uvd);
                else
-                       err("%s: videoStop not set", __FUNCTION__);
+                       err("%s: videoStop not set", __func__);
 
                /* Set packet size to 0 */
                j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
                if (j < 0) {
-                       err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
+                       err("%s: usb_set_interface() error %d.", __func__, j);
                        uvd->last_error = j;
                }
        }
@@ -1955,12 +1957,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        struct usbvideo_frame *frame = &uvd->frame[frameNum];
 
        if (uvd->debug >= 2)
-               info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
+               info("%s($%p,%d.)", __func__, uvd, frameNum);
 
        switch (frame->frameState) {
        case FrameState_Unused:
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Unused", __FUNCTION__);
+                       info("%s: FrameState_Unused", __func__);
                return -EINVAL;
        case FrameState_Ready:
        case FrameState_Grabbing:
@@ -1970,7 +1972,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        redo:
                if (!CAMERA_IS_OPERATIONAL(uvd)) {
                        if (uvd->debug >= 2)
-                               info("%s: Camera is not operational (1)", __FUNCTION__);
+                               info("%s: Camera is not operational (1)", __func__);
                        return -EIO;
                }
                ntries = 0;
@@ -1979,24 +1981,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                        signalPending = signal_pending(current);
                        if (!CAMERA_IS_OPERATIONAL(uvd)) {
                                if (uvd->debug >= 2)
-                                       info("%s: Camera is not operational (2)", __FUNCTION__);
+                                       info("%s: Camera is not operational (2)", __func__);
                                return -EIO;
                        }
                        assert(uvd->fbuf != NULL);
                        if (signalPending) {
                                if (uvd->debug >= 2)
-                                       info("%s: Signal=$%08x", __FUNCTION__, signalPending);
+                                       info("%s: Signal=$%08x", __func__, signalPending);
                                if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
                                        usbvideo_TestPattern(uvd, 1, 0);
                                        uvd->curframe = -1;
                                        uvd->stats.frame_num++;
                                        if (uvd->debug >= 2)
-                                               info("%s: Forced test pattern screen", __FUNCTION__);
+                                               info("%s: Forced test pattern screen", __func__);
                                        return 0;
                                } else {
                                        /* Standard answer: Interrupted! */
                                        if (uvd->debug >= 2)
-                                               info("%s: Interrupted!", __FUNCTION__);
+                                               info("%s: Interrupted!", __func__);
                                        return -EINTR;
                                }
                        } else {
@@ -2006,17 +2008,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                                else if (VALID_CALLBACK(uvd, processData))
                                        GET_CALLBACK(uvd, processData)(uvd, frame);
                                else
-                                       err("%s: processData not set", __FUNCTION__);
+                                       err("%s: processData not set", __func__);
                        }
                } while (frame->frameState == FrameState_Grabbing);
                if (uvd->debug >= 2) {
                        info("%s: Grabbing done; state=%d. (%lu. bytes)",
-                            __FUNCTION__, frame->frameState, frame->seqRead_Length);
+                            __func__, frame->frameState, frame->seqRead_Length);
                }
                if (frame->frameState == FrameState_Error) {
                        int ret = usbvideo_NewFrame(uvd, frameNum);
                        if (ret < 0) {
-                               err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
+                               err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
                                return ret;
                        }
                        goto redo;
@@ -2048,7 +2050,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                }
                frame->frameState = FrameState_Done_Hold;
                if (uvd->debug >= 2)
-                       info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
+                       info("%s: Entered FrameState_Done_Hold state.", __func__);
                return 0;
 
        case FrameState_Done_Hold:
@@ -2059,12 +2061,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                 * it will be released back into the wild to roam freely.
                 */
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Done_Hold state.", __FUNCTION__);
+                       info("%s: FrameState_Done_Hold state.", __func__);
                return 0;
        }
 
        /* Catch-all for other cases. We shall not be here. */
-       err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
+       err("%s: Invalid state %d.", __func__, frame->frameState);
        frame->frameState = FrameState_Unused;
        return 0;
 }
@@ -2160,7 +2162,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
        const int ccm = 128; /* Color correction median - see below */
 
        if ((uvd == NULL) || (frame == NULL)) {
-               err("%s: Illegal call.", __FUNCTION__);
+               err("%s: Illegal call.", __func__);
                return;
        }
        adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
index da1ba0211108939810983cb3753588d713c257ef..64819353276a6a2f2540175625ab0bf42e4fac23 100644 (file)
@@ -48,7 +48,7 @@
 // #define VICAM_DEBUG
 
 #ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
+#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
 #else
 #define DBG(fmn,args...) do {} while(0)
@@ -1066,7 +1066,9 @@ static const struct file_operations vicam_fops = {
        .read           = vicam_read,
        .mmap           = vicam_mmap,
        .ioctl          = vicam_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek         = no_llseek,
 };
 
index 56775ab8b75d386809183403b492dd05671d03ae..a9c5e5adba3afb704c300df72bbbdfe31a2928b8 100644 (file)
 
 #include "usbvision.h"
 
-static unsigned int core_debug = 0;
+static unsigned int core_debug;
 module_param(core_debug,int,0644);
 MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
 
-static unsigned int force_testpattern = 0;
+static unsigned int force_testpattern;
 module_param(force_testpattern,int,0644);
 MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
 
-static int adjustCompression = 1;                      // Set the compression to be adaptive
+static int adjustCompression = 1;      /* Set the compression to be adaptive */
 module_param(adjustCompression, int, 0444);
 MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device.  Default: 1 (On)");
 
-static int SwitchSVideoInput = 0;                      // To help people with Black and White output with using s-video input.  Some cables and input device are wired differently.
+/* To help people with Black and White output with using s-video input.
+ * Some cables and input device are wired differently. */
+static int SwitchSVideoInput;
 module_param(SwitchSVideoInput, int, 0444);
 MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
 
@@ -82,8 +84,10 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
 
 
 #ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) \
-               if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+       #define PDEBUG(level, fmt, args...) { \
+               if (core_debug & (level)) \
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
@@ -384,7 +388,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
        scratch_reset(usbvision);
        if(usbvision->scratch == NULL) {
                err("%s: unable to allocate %d bytes for scratch",
-                   __FUNCTION__, scratch_buf_size);
+                   __func__, scratch_buf_size);
                return -ENOMEM;
        }
        return 0;
@@ -418,7 +422,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision,
        unsigned char *f;
        int num_cell = 0;
        int scan_length = 0;
-       static int num_pass = 0;
+       static int num_pass;
 
        if (usbvision == NULL) {
                printk(KERN_ERR "%s: usbvision == NULL\n", proc);
@@ -493,7 +497,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
        int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
        usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
        if (usbvision->IntraFrameBuffer == NULL) {
-               err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
+               err("%s: unable to allocate %d for compr. frame buffer",
+                   __func__, IFB_size);
                return -ENOMEM;
        }
        return 0;
@@ -1430,7 +1435,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
        }
 #if ENABLE_HEXDUMP
        if (totlen > 0) {
-               static int foo = 0;
+               static int foo;
                if (foo < 1) {
                        printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
                        usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
@@ -1516,7 +1521,7 @@ static void usbvision_isocIrq(struct urb *urb)
 
        if(errCode) {
                err("%s: usb_submit_urb failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
        }
 
        return;
@@ -1547,7 +1552,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
                                0, (__u16) reg, buffer, 1, HZ);
 
        if (errCode < 0) {
-               err("%s: failed: error %d", __FUNCTION__, errCode);
+               err("%s: failed: error %d", __func__, errCode);
                return errCode;
        }
        return buffer[0];
@@ -1575,7 +1580,7 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
                                USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
 
        if (errCode < 0) {
-               err("%s: failed: error %d", __FUNCTION__, errCode);
+               err("%s: failed: error %d", __func__, errCode);
        }
        return errCode;
 }
@@ -1851,7 +1856,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
                                 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
 
                if (errCode < 0) {
-                       err("%s failed: error %d", __FUNCTION__, errCode);
+                       err("%s failed: error %d", __func__, errCode);
                        return errCode;
                }
                usbvision->curwidth = usbvision->stretch_width * UsbWidth;
@@ -2237,7 +2242,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
                             (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
 
        if (rc < 0) {
-               err("%sERROR=%d", __FUNCTION__, rc);
+               err("%sERROR=%d", __func__, rc);
                return rc;
        }
 
@@ -2486,7 +2491,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
 
                urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
                if (urb == NULL) {
-                       err("%s: usb_alloc_urb() failed", __FUNCTION__);
+                       err("%s: usb_alloc_urb() failed", __func__);
                        return -ENOMEM;
                }
                usbvision->sbuf[bufIdx].urb = urb;
@@ -2520,13 +2525,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
                                                 GFP_KERNEL);
                if (errCode) {
                        err("%s: usb_submit_urb(%d) failed: error %d",
-                           __FUNCTION__, bufIdx, errCode);
+                           __func__, bufIdx, errCode);
                }
        }
 
        usbvision->streaming = Stream_Idle;
        PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
-              __FUNCTION__,
+              __func__,
               usbvision->video_endp);
        return 0;
 }
@@ -2560,7 +2565,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
        }
 
 
-       PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
+       PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
        usbvision->streaming = Stream_Off;
 
        if (!usbvision->remove_pending) {
@@ -2571,7 +2576,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
                                            usbvision->ifaceAlt);
                if (errCode < 0) {
                        err("%s: usb_set_interface() failed: error %d",
-                           __FUNCTION__, errCode);
+                           __func__, errCode);
                        usbvision->last_error = errCode;
                }
                regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
index aabc42cae9c7be63b38b6fa3bc9f26b6f12570ba..e2274d77ea295a532befda800eec9ab53e14eb0c 100644 (file)
 
 #define DBG_I2C                1<<0
 
-static int i2c_debug = 0;
+static int i2c_debug;
 
 module_param (i2c_debug, int, 0644);                   // debug_i2c_usb mode of the device driver
 MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
-#define PDEBUG(level, fmt, args...) \
-               if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#define PDEBUG(level, fmt, args...) { \
+               if (i2c_debug & (level)) \
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 
 static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
                            short len);
index df52f8a602155c6c32e26011f6dd93f0c6c7b097..d97261ab430f9f3c772b9ef27f18558a2da5f5fe 100644 (file)
@@ -97,10 +97,10 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 
 
 #ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) \
+       #define PDEBUG(level, fmt, args...) \
                if (video_debug & (level)) \
-                       info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\
-                               ## args)
+                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+       }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
@@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 
 
 /* sequential number of usbvision device */
-static int usbvision_nr = 0;
+static int usbvision_nr;
 
 static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
        { 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
@@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision);
 /* Set the default format for ISOC endpoint */
 static int isocMode = ISOC_MODE_COMPRESS;
 /* Set the default Debug Mode of the device driver */
-static int video_debug = 0;
+static int video_debug;
 /* Set the default device to power on at startup */
 static int PowerOnAtOpen = 1;
 /* Sequential Number of Video Device */
@@ -343,7 +343,7 @@ static void usbvision_create_sysfs(struct video_device *vdev)
                        return;
        } while (0);
 
-       err("%s error: %d\n", __FUNCTION__, res);
+       err("%s error: %d\n", __func__, res);
 }
 
 static void usbvision_remove_sysfs(struct video_device *vdev)
@@ -490,7 +490,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
        mutex_unlock(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
        }
 
@@ -522,7 +522,7 @@ static int vidioc_g_register (struct file *file, void *priv,
        errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
        if (errCode < 0) {
                err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
                return errCode;
        }
        reg->val = errCode;
@@ -543,7 +543,7 @@ static int vidioc_s_register (struct file *file, void *priv,
        errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
        if (errCode < 0) {
                err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
-                   __FUNCTION__, errCode);
+                   __func__, errCode);
                return errCode;
        }
        return 0;
@@ -1102,7 +1102,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        int ret,i;
        struct usbvision_frame *frame;
 
-       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__,
+       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
               (unsigned long)count, noblock);
 
        if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
@@ -1171,7 +1171,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        }
 
        PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
-              __FUNCTION__,
+              __func__,
               frame->index, frame->bytes_read, frame->scanlength);
 
        /* copy bytes to user space; we allow for partials reads */
@@ -1184,7 +1184,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
 
        frame->bytes_read += count;
        PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
-              __FUNCTION__,
+              __func__,
               (unsigned long)count, frame->bytes_read);
 
        /* For now, forget the frame if it has not been read in one shot. */
@@ -1269,12 +1269,12 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
                (struct usb_usbvision *) video_get_drvdata(dev);
        int errCode = 0;
 
-       PDEBUG(DBG_IO, "%s:", __FUNCTION__);
+       PDEBUG(DBG_IO, "%s:", __func__);
 
        mutex_lock(&usbvision->lock);
 
        if (usbvision->user) {
-               err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
+               err("%s: Someone tried to open an already opened USBVision Radio!", __func__);
                errCode = -EBUSY;
        }
        else {
@@ -1342,7 +1342,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
        mutex_unlock(&usbvision->lock);
 
        if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
        }
 
@@ -1507,7 +1507,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
        struct video_device *vdev;
 
        if (usb_dev == NULL) {
-               err("%s: usbvision->dev is not set", __FUNCTION__);
+               err("%s: usbvision->dev is not set", __func__);
                return NULL;
        }
 
@@ -1759,7 +1759,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
                PDEBUG(DBG_PROBE, "model out of bounds %d",model);
                return -ENODEV;
        }
-       printk(KERN_INFO "%s: %s found\n", __FUNCTION__,
+       printk(KERN_INFO "%s: %s found\n", __func__,
                                usbvision_device_data[model].ModelString);
 
        if (usbvision_device_data[model].Interface >= 0) {
@@ -1771,20 +1771,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
            USB_ENDPOINT_XFER_ISOC) {
                err("%s: interface %d. has non-ISO endpoint!",
-                   __FUNCTION__, ifnum);
+                   __func__, ifnum);
                err("%s: Endpoint attributes %d",
-                   __FUNCTION__, endpoint->bmAttributes);
+                   __func__, endpoint->bmAttributes);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
            USB_DIR_OUT) {
                err("%s: interface %d. has ISO OUT endpoint!",
-                   __FUNCTION__, ifnum);
+                   __func__, ifnum);
                return -ENODEV;
        }
 
        if ((usbvision = usbvision_alloc(dev)) == NULL) {
-               err("%s: couldn't allocate USBVision struct", __FUNCTION__);
+               err("%s: couldn't allocate USBVision struct", __func__);
                return -ENOMEM;
        }
 
@@ -1868,7 +1868,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
        PDEBUG(DBG_PROBE, "");
 
        if (usbvision == NULL) {
-               err("%s: usb_get_intfdata() failed", __FUNCTION__);
+               err("%s: usb_get_intfdata() failed", __func__);
                return;
        }
        usb_set_intfdata (intf, NULL);
@@ -1891,7 +1891,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
 
        if (usbvision->user) {
                printk(KERN_INFO "%s: In use, disconnect pending\n",
-                      __FUNCTION__);
+                      __func__);
                wake_up_interruptible(&usbvision->wait_frame);
                wake_up_interruptible(&usbvision->wait_stream);
        } else {
index e3ac5e6860758c6e6a7e1bd83ef11eadd4b9f6ad..a0f6c60279ece8cb97cc69612889e0a646beae63 100644 (file)
 #include <linux/kmod.h>
 #endif
 
-static unsigned int debug  = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+MODULE_PARM_DESC(debug, "enable debug messages");
 MODULE_AUTHOR("Bill Dirks");
 MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
 MODULE_LICENSE("GPL");
 
-#define dprintk(fmt, arg...)   if (debug) \
-       printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
+#define dprintk(fmt, arg...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
+       } while (0)
 
 /*
  *     I O C T L   T R A N S L A T I O N
@@ -69,14 +72,12 @@ get_v4l_control(struct inode            *inode,
        qctrl2.id = cid;
        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
        if (err < 0)
-               dprintk("VIDIOC_QUERYCTRL: %d\n",err);
-       if (err == 0 &&
-           !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
-       {
+               dprintk("VIDIOC_QUERYCTRL: %d\n", err);
+       if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
                ctrl2.id = qctrl2.id;
                err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
                if (err < 0) {
-                       dprintk("VIDIOC_G_CTRL: %d\n",err);
+                       dprintk("VIDIOC_G_CTRL: %d\n", err);
                        return 0;
                }
                return ((ctrl2.value - qctrl2.minimum) * 65535
@@ -100,11 +101,10 @@ set_v4l_control(struct inode            *inode,
        qctrl2.id = cid;
        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
        if (err < 0)
-               dprintk("VIDIOC_QUERYCTRL: %d\n",err);
+               dprintk("VIDIOC_QUERYCTRL: %d\n", err);
        if (err == 0 &&
            !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
-           !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
-       {
+           !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
                if (value < 0)
                        value = 0;
                if (value > 65535)
@@ -119,7 +119,7 @@ set_v4l_control(struct inode            *inode,
                ctrl2.value += qctrl2.minimum;
                err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
                if (err < 0)
-                       dprintk("VIDIOC_S_CTRL: %d\n",err);
+                       dprintk("VIDIOC_S_CTRL: %d\n", err);
        }
        return 0;
 }
@@ -157,8 +157,7 @@ static unsigned int __attribute_const__
 pixelformat_to_palette(unsigned int pixelformat)
 {
        int     palette = 0;
-       switch (pixelformat)
-       {
+       switch (pixelformat) {
        case V4L2_PIX_FMT_GREY:
                palette = VIDEO_PALETTE_GREY;
                break;
@@ -200,14 +199,13 @@ pixelformat_to_palette(unsigned int pixelformat)
 
 /* ----------------------------------------------------------------- */
 
-static int poll_one(struct file *file)
+static int poll_one(struct file *file, struct poll_wqueues *pwq)
 {
        int retval = 1;
        poll_table *table;
-       struct poll_wqueues pwq;
 
-       poll_initwait(&pwq);
-       table = &pwq.pt;
+       poll_initwait(pwq);
+       table = &pwq->pt;
        for (;;) {
                int mask;
                set_current_state(TASK_INTERRUPTIBLE);
@@ -222,878 +220,1073 @@ static int poll_one(struct file *file)
                schedule();
        }
        set_current_state(TASK_RUNNING);
-       poll_freewait(&pwq);
+       poll_freewait(pwq);
        return retval;
 }
 
-static int count_inputs(struct inode         *inode,
-                       struct file          *file,
-                       v4l2_kioctl          drv)
+static int count_inputs(
+                       struct inode *inode,
+                       struct file *file,
+                       v4l2_kioctl drv)
 {
        struct v4l2_input input2;
        int i;
 
        for (i = 0;; i++) {
-               memset(&input2,0,sizeof(input2));
+               memset(&input2, 0, sizeof(input2));
                input2.index = i;
-               if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
+               if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
                        break;
        }
        return i;
 }
 
-static int check_size(struct inode         *inode,
-                     struct file          *file,
-                     v4l2_kioctl          drv,
-                     int *maxw, int *maxh)
+static int check_size(
+               struct inode *inode,
+               struct file *file,
+               v4l2_kioctl drv,
+               int *maxw,
+               int *maxh)
 {
        struct v4l2_fmtdesc desc2;
        struct v4l2_format  fmt2;
 
-       memset(&desc2,0,sizeof(desc2));
-       memset(&fmt2,0,sizeof(fmt2));
+       memset(&desc2, 0, sizeof(desc2));
+       memset(&fmt2, 0, sizeof(fmt2));
 
        desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
+       if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
                goto done;
 
        fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt2.fmt.pix.width       = 10000;
        fmt2.fmt.pix.height      = 10000;
        fmt2.fmt.pix.pixelformat = desc2.pixelformat;
-       if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
+       if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
                goto done;
 
        *maxw = fmt2.fmt.pix.width;
        *maxh = fmt2.fmt.pix.height;
 
- done:
+done:
        return 0;
 }
 
 /* ----------------------------------------------------------------- */
 
-/*
- *     This function is exported.
- */
-int
-v4l_compat_translate_ioctl(struct inode         *inode,
-                          struct file          *file,
-                          int                  cmd,
-                          void                 *arg,
-                          v4l2_kioctl          drv)
+static noinline int v4l1_compat_get_capabilities(
+                                       struct video_capability *cap,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
 {
-       struct v4l2_capability  *cap2 = NULL;
-       struct v4l2_format      *fmt2 = NULL;
-       enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       struct v4l2_framebuffer fbuf2;
-       struct v4l2_input       input2;
-       struct v4l2_tuner       tun2;
-       struct v4l2_standard    std2;
-       struct v4l2_frequency   freq2;
-       struct v4l2_audio       aud2;
-       struct v4l2_queryctrl   qctrl2;
-       struct v4l2_buffer      buf2;
-       v4l2_std_id             sid;
-       int i, err = 0;
-
-       switch (cmd) {
-       case VIDIOCGCAP:        /* capability */
-       {
-               struct video_capability *cap = arg;
-
-               cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
-               if (!cap2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(cap, 0, sizeof(*cap));
-               memset(&fbuf2, 0, sizeof(fbuf2));
+       int err;
+       struct v4l2_framebuffer fbuf;
+       struct v4l2_capability *cap2;
+
+       cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
+       if (!cap2) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(cap, 0, sizeof(*cap));
+       memset(&fbuf, 0, sizeof(fbuf));
 
-               err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+       err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+       if (err < 0) {
+               dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
+               goto done;
+       }
+       if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
+               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
                if (err < 0) {
-                       dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
-                       break;
+                       dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
+                       memset(&fbuf, 0, sizeof(fbuf));
                }
-               if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
-                       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-                       if (err < 0) {
-                               dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
-                               memset(&fbuf2, 0, sizeof(fbuf2));
-                       }
-                       err = 0;
-               }
-
-               memcpy(cap->name, cap2->card,
-                      min(sizeof(cap->name), sizeof(cap2->card)));
-               cap->name[sizeof(cap->name) - 1] = 0;
-               if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
-                       cap->type |= VID_TYPE_CAPTURE;
-               if (cap2->capabilities & V4L2_CAP_TUNER)
-                       cap->type |= VID_TYPE_TUNER;
-               if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
-                       cap->type |= VID_TYPE_TELETEXT;
-               if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
-                       cap->type |= VID_TYPE_OVERLAY;
-               if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
-                       cap->type |= VID_TYPE_CLIPPING;
-
-               cap->channels  = count_inputs(inode,file,drv);
-               check_size(inode,file,drv,
-                          &cap->maxwidth,&cap->maxheight);
-               cap->audios    =  0; /* FIXME */
-               cap->minwidth  = 48; /* FIXME */
-               cap->minheight = 32; /* FIXME */
-               break;
+               err = 0;
        }
-       case VIDIOCGFBUF: /*  get frame buffer  */
-       {
-               struct video_buffer     *buffer = arg;
 
-               memset(buffer, 0, sizeof(*buffer));
-               memset(&fbuf2, 0, sizeof(fbuf2));
+       memcpy(cap->name, cap2->card,
+              min(sizeof(cap->name), sizeof(cap2->card)));
+       cap->name[sizeof(cap->name) - 1] = 0;
+       if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
+               cap->type |= VID_TYPE_CAPTURE;
+       if (cap2->capabilities & V4L2_CAP_TUNER)
+               cap->type |= VID_TYPE_TUNER;
+       if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
+               cap->type |= VID_TYPE_TELETEXT;
+       if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
+               cap->type |= VID_TYPE_OVERLAY;
+       if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
+               cap->type |= VID_TYPE_CLIPPING;
+
+       cap->channels  = count_inputs(inode, file, drv);
+       check_size(inode, file, drv,
+                  &cap->maxwidth, &cap->maxheight);
+       cap->audios    =  0; /* FIXME */
+       cap->minwidth  = 48; /* FIXME */
+       cap->minheight = 32; /* FIXME */
+
+done:
+       kfree(cap2);
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-               if (err < 0) {
-                       dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
-                       break;
-               }
-               buffer->base   = fbuf2.base;
-               buffer->height = fbuf2.fmt.height;
-               buffer->width  = fbuf2.fmt.width;
+static noinline int v4l1_compat_get_frame_buffer(
+                                       struct video_buffer *buffer,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
 
-               switch (fbuf2.fmt.pixelformat) {
-               case V4L2_PIX_FMT_RGB332:
-                       buffer->depth = 8;
-                       break;
-               case V4L2_PIX_FMT_RGB555:
-                       buffer->depth = 15;
-                       break;
-               case V4L2_PIX_FMT_RGB565:
-                       buffer->depth = 16;
-                       break;
-               case V4L2_PIX_FMT_BGR24:
-                       buffer->depth = 24;
-                       break;
-               case V4L2_PIX_FMT_BGR32:
-                       buffer->depth = 32;
-                       break;
-               default:
-                       buffer->depth = 0;
-               }
-               if (fbuf2.fmt.bytesperline) {
-                       buffer->bytesperline = fbuf2.fmt.bytesperline;
-                       if (!buffer->depth && buffer->width)
-                               buffer->depth   = ((fbuf2.fmt.bytesperline<<3)
-                                                 + (buffer->width-1) )
-                                                 /buffer->width;
-               } else {
-                       buffer->bytesperline =
-                               (buffer->width * buffer->depth + 7) & 7;
-                       buffer->bytesperline >>= 3;
-               }
+       memset(buffer, 0, sizeof(*buffer));
+       memset(&fbuf, 0, sizeof(fbuf));
+
+       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+       if (err < 0) {
+               dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
+               goto done;
+       }
+       buffer->base   = fbuf.base;
+       buffer->height = fbuf.fmt.height;
+       buffer->width  = fbuf.fmt.width;
+
+       switch (fbuf.fmt.pixelformat) {
+       case V4L2_PIX_FMT_RGB332:
+               buffer->depth = 8;
+               break;
+       case V4L2_PIX_FMT_RGB555:
+               buffer->depth = 15;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               buffer->depth = 16;
+               break;
+       case V4L2_PIX_FMT_BGR24:
+               buffer->depth = 24;
+               break;
+       case V4L2_PIX_FMT_BGR32:
+               buffer->depth = 32;
                break;
+       default:
+               buffer->depth = 0;
        }
-       case VIDIOCSFBUF: /*  set frame buffer  */
-       {
-               struct video_buffer     *buffer = arg;
-
-               memset(&fbuf2, 0, sizeof(fbuf2));
-               fbuf2.base       = buffer->base;
-               fbuf2.fmt.height = buffer->height;
-               fbuf2.fmt.width  = buffer->width;
-               switch (buffer->depth) {
-               case 8:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
-                       break;
-               case 15:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
-                       break;
-               case 16:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
-                       break;
-               case 24:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
-                       break;
-               case 32:
-                       fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
-                       break;
-               }
-               fbuf2.fmt.bytesperline = buffer->bytesperline;
-               err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
-               if (err < 0)
-                       dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
+       if (fbuf.fmt.bytesperline) {
+               buffer->bytesperline = fbuf.fmt.bytesperline;
+               if (!buffer->depth && buffer->width)
+                       buffer->depth   = ((fbuf.fmt.bytesperline<<3)
+                                         + (buffer->width-1))
+                                         / buffer->width;
+       } else {
+               buffer->bytesperline =
+                       (buffer->width * buffer->depth + 7) & 7;
+               buffer->bytesperline >>= 3;
+       }
+done:
+       return err;
+}
+
+static noinline int v4l1_compat_set_frame_buffer(
+                                       struct video_buffer *buffer,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
+
+       memset(&fbuf, 0, sizeof(fbuf));
+       fbuf.base       = buffer->base;
+       fbuf.fmt.height = buffer->height;
+       fbuf.fmt.width  = buffer->width;
+       switch (buffer->depth) {
+       case 8:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
+               break;
+       case 15:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
+               break;
+       case 16:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+               break;
+       case 24:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+               break;
+       case 32:
+               fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
                break;
        }
-       case VIDIOCGWIN: /*  get window or capture dimensions  */
-       {
-               struct video_window     *win = arg;
+       fbuf.fmt.bytesperline = buffer->bytesperline;
+       err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+       if (err < 0)
+               dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(win,0,sizeof(*win));
+static noinline int v4l1_compat_get_win_cap_dimensions(
+                                       struct video_window *win,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt;
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0)
-                       dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
-               if (err == 0) {
-                       win->x         = fmt2->fmt.win.w.left;
-                       win->y         = fmt2->fmt.win.w.top;
-                       win->width     = fmt2->fmt.win.w.width;
-                       win->height    = fmt2->fmt.win.w.height;
-                       win->chromakey = fmt2->fmt.win.chromakey;
-                       win->clips     = NULL;
-                       win->clipcount = 0;
-                       break;
-               }
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(win, 0, sizeof(*win));
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
-                       break;
-               }
-               win->x         = 0;
-               win->y         = 0;
-               win->width     = fmt2->fmt.pix.width;
-               win->height    = fmt2->fmt.pix.height;
-               win->chromakey = 0;
+       fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0)
+               dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
+       if (err == 0) {
+               win->x         = fmt->fmt.win.w.left;
+               win->y         = fmt->fmt.win.w.top;
+               win->width     = fmt->fmt.win.w.width;
+               win->height    = fmt->fmt.win.w.height;
+               win->chromakey = fmt->fmt.win.chromakey;
                win->clips     = NULL;
                win->clipcount = 0;
-               break;
+               goto done;
        }
-       case VIDIOCSWIN: /*  set window and/or capture dimensions  */
-       {
-               struct video_window     *win = arg;
-               int err1,err2;
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
-               err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err1 < 0)
-                       dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
-               if (err1 == 0) {
-                       fmt2->fmt.pix.width  = win->width;
-                       fmt2->fmt.pix.height = win->height;
-                       fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
-                       fmt2->fmt.pix.bytesperline = 0;
-                       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (err < 0)
-                               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
-                                       err);
-                       win->width  = fmt2->fmt.pix.width;
-                       win->height = fmt2->fmt.pix.height;
-               }
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       win->x         = 0;
+       win->y         = 0;
+       win->width     = fmt->fmt.pix.width;
+       win->height    = fmt->fmt.pix.height;
+       win->chromakey = 0;
+       win->clips     = NULL;
+       win->clipcount = 0;
+done:
+       kfree(fmt);
+       return err;
+}
 
-               memset(fmt2,0,sizeof(*fmt2));
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               fmt2->fmt.win.w.left    = win->x;
-               fmt2->fmt.win.w.top     = win->y;
-               fmt2->fmt.win.w.width   = win->width;
-               fmt2->fmt.win.w.height  = win->height;
-               fmt2->fmt.win.chromakey = win->chromakey;
-               fmt2->fmt.win.clips     = (void __user *)win->clips;
-               fmt2->fmt.win.clipcount = win->clipcount;
-               err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
-               if (err2 < 0)
-                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
-
-               if (err1 != 0 && err2 != 0)
-                       err = err1;
-               break;
+static noinline int v4l1_compat_set_win_cap_dimensions(
+                                       struct video_window *win,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, err1, err2;
+       struct v4l2_format *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCCAPTURE: /*  turn on/off preview  */
-       {
-               int *on = arg;
-
-               if (0 == *on) {
-                       /* dirty hack time.  But v4l1 has no STREAMOFF
-                        * equivalent in the API, and this one at
-                        * least comes close ... */
-                       drv(inode, file, VIDIOC_STREAMOFF, &captype);
-               }
-               err = drv(inode, file, VIDIOC_OVERLAY, arg);
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
+       err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err1 < 0)
+               dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
+       if (err1 == 0) {
+               fmt->fmt.pix.width  = win->width;
+               fmt->fmt.pix.height = win->height;
+               fmt->fmt.pix.field  = V4L2_FIELD_ANY;
+               fmt->fmt.pix.bytesperline = 0;
+               err = drv(inode, file, VIDIOC_S_FMT, fmt);
                if (err < 0)
-                       dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
-               break;
+                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+                               err);
+               win->width  = fmt->fmt.pix.width;
+               win->height = fmt->fmt.pix.height;
        }
-       case VIDIOCGCHAN: /*  get input information  */
-       {
-               struct video_channel    *chan = arg;
 
-               memset(&input2,0,sizeof(input2));
-               input2.index = chan->channel;
-               err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
-               if (err < 0) {
-                       dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
-                               "channel=%d err=%d\n",chan->channel,err);
-                       break;
-               }
-               chan->channel = input2.index;
-               memcpy(chan->name, input2.name,
-                      min(sizeof(chan->name), sizeof(input2.name)));
-               chan->name[sizeof(chan->name) - 1] = 0;
-               chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
-               chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
-               switch (input2.type) {
-               case V4L2_INPUT_TYPE_TUNER:
-                       chan->type = VIDEO_TYPE_TV;
-                       break;
-               default:
-               case V4L2_INPUT_TYPE_CAMERA:
-                       chan->type = VIDEO_TYPE_CAMERA;
-                       break;
-               }
-               chan->norm = 0;
-               err = drv(inode, file, VIDIOC_G_STD, &sid);
-               if (err < 0)
-                       dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
-               if (err == 0) {
-                       if (sid & V4L2_STD_PAL)
-                               chan->norm = VIDEO_MODE_PAL;
-                       if (sid & V4L2_STD_NTSC)
-                               chan->norm = VIDEO_MODE_NTSC;
-                       if (sid & V4L2_STD_SECAM)
-                               chan->norm = VIDEO_MODE_SECAM;
-               }
-               break;
-       }
-       case VIDIOCSCHAN: /*  set input  */
-       {
-               struct video_channel *chan = arg;
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+       fmt->fmt.win.w.left    = win->x;
+       fmt->fmt.win.w.top     = win->y;
+       fmt->fmt.win.w.width   = win->width;
+       fmt->fmt.win.w.height  = win->height;
+       fmt->fmt.win.chromakey = win->chromakey;
+       fmt->fmt.win.clips     = (void __user *)win->clips;
+       fmt->fmt.win.clipcount = win->clipcount;
+       err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
+       if (err2 < 0)
+               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
+
+       if (err1 != 0 && err2 != 0)
+               err = err1;
+       else
+               err = 0;
+       kfree(fmt);
+       return err;
+}
 
-               sid = 0;
-               err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
-               if (err < 0)
-                       dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
-               switch (chan->norm) {
-               case VIDEO_MODE_PAL:
-                       sid = V4L2_STD_PAL;
-                       break;
-               case VIDEO_MODE_NTSC:
-                       sid = V4L2_STD_NTSC;
-                       break;
-               case VIDEO_MODE_SECAM:
-                       sid = V4L2_STD_SECAM;
-                       break;
-               }
-               if (0 != sid) {
-                       err = drv(inode, file, VIDIOC_S_STD, &sid);
-                       if (err < 0)
-                               dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
-               }
-               break;
+static noinline int v4l1_compat_turn_preview_on_off(
+                                       int *on,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (0 == *on) {
+               /* dirty hack time.  But v4l1 has no STREAMOFF
+                * equivalent in the API, and this one at
+                * least comes close ... */
+               drv(inode, file, VIDIOC_STREAMOFF, &captype);
        }
-       case VIDIOCGPICT: /*  get tone controls & partial capture format  */
-       {
-               struct video_picture    *pict = arg;
-
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
+       err = drv(inode, file, VIDIOC_OVERLAY, on);
+       if (err < 0)
+               dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
+       return err;
+}
 
-               pict->brightness = get_v4l_control(inode, file,
-                                                  V4L2_CID_BRIGHTNESS,drv);
-               pict->hue = get_v4l_control(inode, file,
-                                           V4L2_CID_HUE, drv);
-               pict->contrast = get_v4l_control(inode, file,
-                                                V4L2_CID_CONTRAST, drv);
-               pict->colour = get_v4l_control(inode, file,
-                                              V4L2_CID_SATURATION, drv);
-               pict->whiteness = get_v4l_control(inode, file,
-                                                 V4L2_CID_WHITENESS, drv);
-
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
-                       break;
-               }
+static noinline int v4l1_compat_get_input_info(
+                                       struct video_channel *chan,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_input       input2;
+       v4l2_std_id             sid;
 
-               pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
-                                + (fmt2->fmt.pix.width-1) )
-                                /fmt2->fmt.pix.width;
-               pict->palette = pixelformat_to_palette(
-                       fmt2->fmt.pix.pixelformat);
+       memset(&input2, 0, sizeof(input2));
+       input2.index = chan->channel;
+       err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+       if (err < 0) {
+               dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
+                       "channel=%d err=%d\n", chan->channel, err);
+               goto done;
+       }
+       chan->channel = input2.index;
+       memcpy(chan->name, input2.name,
+              min(sizeof(chan->name), sizeof(input2.name)));
+       chan->name[sizeof(chan->name) - 1] = 0;
+       chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
+       chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
+       switch (input2.type) {
+       case V4L2_INPUT_TYPE_TUNER:
+               chan->type = VIDEO_TYPE_TV;
+               break;
+       default:
+       case V4L2_INPUT_TYPE_CAMERA:
+               chan->type = VIDEO_TYPE_CAMERA;
                break;
        }
-       case VIDIOCSPICT: /*  set tone controls & partial capture format  */
-       {
-               struct video_picture    *pict = arg;
-               int mem_err = 0, ovl_err = 0;
+       chan->norm = 0;
+       err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (err < 0)
+               dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
+       if (err == 0) {
+               if (sid & V4L2_STD_PAL)
+                       chan->norm = VIDEO_MODE_PAL;
+               if (sid & V4L2_STD_NTSC)
+                       chan->norm = VIDEO_MODE_NTSC;
+               if (sid & V4L2_STD_SECAM)
+                       chan->norm = VIDEO_MODE_SECAM;
+       }
+done:
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(&fbuf2, 0, sizeof(fbuf2));
-
-               set_v4l_control(inode, file,
-                               V4L2_CID_BRIGHTNESS, pict->brightness, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_HUE, pict->hue, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_CONTRAST, pict->contrast, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_SATURATION, pict->colour, drv);
-               set_v4l_control(inode, file,
-                               V4L2_CID_WHITENESS, pict->whiteness, drv);
-               /*
-                * V4L1 uses this ioctl to set both memory capture and overlay
-                * pixel format, while V4L2 has two different ioctls for this.
-                * Some cards may not support one or the other, and may support
-                * different pixel formats for memory vs overlay.
-                */
-
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               /* If VIDIOC_G_FMT failed, then the driver likely doesn't
-                  support memory capture.  Trying to set the memory capture
-                  parameters would be pointless.  */
-               if (err < 0) {
-                       dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
-                       mem_err = -1000;  /* didn't even try */
-               } else if (fmt2->fmt.pix.pixelformat !=
-                        palette_to_pixelformat(pict->palette)) {
-                       fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
-                               pict->palette);
-                       mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (mem_err < 0)
-                               dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
-                                       mem_err);
-               }
+static noinline int v4l1_compat_set_input(
+                                       struct video_channel *chan,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       v4l2_std_id sid = 0;
 
-               err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-               /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
-                  support overlay.  Trying to set the overlay parameters
-                  would be quite pointless.  */
-               if (err < 0) {
-                       dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
-                       ovl_err = -1000;  /* didn't even try */
-               } else if (fbuf2.fmt.pixelformat !=
-                        palette_to_pixelformat(pict->palette)) {
-                       fbuf2.fmt.pixelformat = palette_to_pixelformat(
-                               pict->palette);
-                       ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
-                       if (ovl_err < 0)
-                               dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
-                                       ovl_err);
-               }
-               if (ovl_err < 0 && mem_err < 0)
-                       /* ioctl failed, couldn't set either parameter */
-                       if (mem_err != -1000) {
-                           err = mem_err;
-                       } else if (ovl_err == -EPERM) {
-                           err = 0;
-                       } else {
-                           err = ovl_err;
-                       }
-               else
-                       err = 0;
+       err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+       if (err < 0)
+               dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
+       switch (chan->norm) {
+       case VIDEO_MODE_PAL:
+               sid = V4L2_STD_PAL;
+               break;
+       case VIDEO_MODE_NTSC:
+               sid = V4L2_STD_NTSC;
+               break;
+       case VIDEO_MODE_SECAM:
+               sid = V4L2_STD_SECAM;
                break;
        }
-       case VIDIOCGTUNER: /*  get tuner information  */
-       {
-               struct video_tuner      *tun = arg;
-
-               memset(&tun2,0,sizeof(tun2));
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0) {
-                       dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
-                       break;
-               }
-               memcpy(tun->name, tun2.name,
-                      min(sizeof(tun->name), sizeof(tun2.name)));
-               tun->name[sizeof(tun->name) - 1] = 0;
-               tun->rangelow = tun2.rangelow;
-               tun->rangehigh = tun2.rangehigh;
-               tun->flags = 0;
-               tun->mode = VIDEO_MODE_AUTO;
-
-               for (i = 0; i < 64; i++) {
-                       memset(&std2,0,sizeof(std2));
-                       std2.index = i;
-                       if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
-                               break;
-                       if (std2.id & V4L2_STD_PAL)
-                               tun->flags |= VIDEO_TUNER_PAL;
-                       if (std2.id & V4L2_STD_NTSC)
-                               tun->flags |= VIDEO_TUNER_NTSC;
-                       if (std2.id & V4L2_STD_SECAM)
-                               tun->flags |= VIDEO_TUNER_SECAM;
-               }
-
-               err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (0 != sid) {
+               err = drv(inode, file, VIDIOC_S_STD, &sid);
                if (err < 0)
-                       dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
-               if (err == 0) {
-                       if (sid & V4L2_STD_PAL)
-                               tun->mode = VIDEO_MODE_PAL;
-                       if (sid & V4L2_STD_NTSC)
-                               tun->mode = VIDEO_MODE_NTSC;
-                       if (sid & V4L2_STD_SECAM)
-                               tun->mode = VIDEO_MODE_SECAM;
-               }
-
-               if (tun2.capability & V4L2_TUNER_CAP_LOW)
-                       tun->flags |= VIDEO_TUNER_LOW;
-               if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-                       tun->flags |= VIDEO_TUNER_STEREO_ON;
-               tun->signal = tun2.signal;
-               break;
+                       dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
        }
-       case VIDIOCSTUNER: /*  select a tuner input  */
-       {
-               struct video_tuner      *tun = arg;
-               struct v4l2_tuner       t;
-               memset(&t,0,sizeof(t));
-
-               t.index=tun->tuner;
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_S_INPUT, &t);
-               if (err < 0)
-                       dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+static noinline int v4l1_compat_get_picture(
+                                       struct video_picture *pict,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt;
 
-               break;
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCGFREQ: /*  get frequency  */
-       {
-               unsigned long *freq = arg;
-               memset(&freq2,0,sizeof(freq2));
 
-               freq2.tuner = 0;
-               err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
-               if (err < 0)
-                       dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
-               if (0 == err)
-                       *freq = freq2.frequency;
-               break;
+       pict->brightness = get_v4l_control(inode, file,
+                                          V4L2_CID_BRIGHTNESS, drv);
+       pict->hue = get_v4l_control(inode, file,
+                                   V4L2_CID_HUE, drv);
+       pict->contrast = get_v4l_control(inode, file,
+                                        V4L2_CID_CONTRAST, drv);
+       pict->colour = get_v4l_control(inode, file,
+                                      V4L2_CID_SATURATION, drv);
+       pict->whiteness = get_v4l_control(inode, file,
+                                         V4L2_CID_WHITENESS, drv);
+
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
+               goto done;
        }
-       case VIDIOCSFREQ: /*  set frequency  */
-       {
-               unsigned long *freq = arg;
-               memset(&freq2,0,sizeof(freq2));
 
-               drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
-               freq2.frequency = *freq;
-               err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
-               if (err < 0)
-                       dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
-               break;
+       pict->depth   = ((fmt->fmt.pix.bytesperline << 3)
+                        + (fmt->fmt.pix.width - 1))
+                        / fmt->fmt.pix.width;
+       pict->palette = pixelformat_to_palette(
+               fmt->fmt.pix.pixelformat);
+done:
+       kfree(fmt);
+       return err;
+}
+
+static noinline int v4l1_compat_set_picture(
+                                       struct video_picture *pict,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_framebuffer fbuf;
+       int mem_err = 0, ovl_err = 0;
+       struct v4l2_format *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(&fbuf, 0, sizeof(fbuf));
+
+       set_v4l_control(inode, file,
+                       V4L2_CID_BRIGHTNESS, pict->brightness, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_HUE, pict->hue, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_CONTRAST, pict->contrast, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_SATURATION, pict->colour, drv);
+       set_v4l_control(inode, file,
+                       V4L2_CID_WHITENESS, pict->whiteness, drv);
+       /*
+        * V4L1 uses this ioctl to set both memory capture and overlay
+        * pixel format, while V4L2 has two different ioctls for this.
+        * Some cards may not support one or the other, and may support
+        * different pixel formats for memory vs overlay.
+        */
+
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       /* If VIDIOC_G_FMT failed, then the driver likely doesn't
+          support memory capture.  Trying to set the memory capture
+          parameters would be pointless.  */
+       if (err < 0) {
+               dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
+               mem_err = -1000;  /* didn't even try */
+       } else if (fmt->fmt.pix.pixelformat !=
+                palette_to_pixelformat(pict->palette)) {
+               fmt->fmt.pix.pixelformat = palette_to_pixelformat(
+                       pict->palette);
+               mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
+               if (mem_err < 0)
+                       dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+                               mem_err);
        }
-       case VIDIOCGAUDIO: /*  get audio properties/controls  */
-       {
-               struct video_audio      *aud = arg;
-               memset(&aud2,0,sizeof(aud2));
 
-               err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
-               if (err < 0) {
-                       dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
-                       break;
-               }
-               memcpy(aud->name, aud2.name,
-                      min(sizeof(aud->name), sizeof(aud2.name)));
-               aud->name[sizeof(aud->name) - 1] = 0;
-               aud->audio = aud2.index;
-               aud->flags = 0;
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
-               if (i >= 0) {
-                       aud->volume = i;
-                       aud->flags |= VIDEO_AUDIO_VOLUME;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
-               if (i >= 0) {
-                       aud->bass = i;
-                       aud->flags |= VIDEO_AUDIO_BASS;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
-               if (i >= 0) {
-                       aud->treble = i;
-                       aud->flags |= VIDEO_AUDIO_TREBLE;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
-               if (i >= 0) {
-                       aud->balance = i;
-                       aud->flags |= VIDEO_AUDIO_BALANCE;
-               }
-               i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
-               if (i >= 0) {
-                       if (i)
-                               aud->flags |= VIDEO_AUDIO_MUTE;
-                       aud->flags |= VIDEO_AUDIO_MUTABLE;
-               }
-               aud->step = 1;
-               qctrl2.id = V4L2_CID_AUDIO_VOLUME;
-               if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
-                   !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
-                       aud->step = qctrl2.step;
-               aud->mode = 0;
-
-               memset(&tun2,0,sizeof(tun2));
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0) {
-                       dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
+       err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+       /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+          support overlay.  Trying to set the overlay parameters
+          would be quite pointless.  */
+       if (err < 0) {
+               dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
+               ovl_err = -1000;  /* didn't even try */
+       } else if (fbuf.fmt.pixelformat !=
+                palette_to_pixelformat(pict->palette)) {
+               fbuf.fmt.pixelformat = palette_to_pixelformat(
+                       pict->palette);
+               ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+               if (ovl_err < 0)
+                       dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+                               ovl_err);
+       }
+       if (ovl_err < 0 && mem_err < 0) {
+               /* ioctl failed, couldn't set either parameter */
+               if (mem_err != -1000)
+                       err = mem_err;
+               else if (ovl_err == -EPERM)
                        err = 0;
+               else
+                       err = ovl_err;
+       } else
+               err = 0;
+       kfree(fmt);
+       return err;
+}
+
+static noinline int v4l1_compat_get_tuner(
+                                       struct video_tuner *tun,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, i;
+       struct v4l2_tuner       tun2;
+       struct v4l2_standard    std2;
+       v4l2_std_id             sid;
+
+       memset(&tun2, 0, sizeof(tun2));
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0) {
+               dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
+               goto done;
+       }
+       memcpy(tun->name, tun2.name,
+              min(sizeof(tun->name), sizeof(tun2.name)));
+       tun->name[sizeof(tun->name) - 1] = 0;
+       tun->rangelow = tun2.rangelow;
+       tun->rangehigh = tun2.rangehigh;
+       tun->flags = 0;
+       tun->mode = VIDEO_MODE_AUTO;
+
+       for (i = 0; i < 64; i++) {
+               memset(&std2, 0, sizeof(std2));
+               std2.index = i;
+               if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
                        break;
-               }
+               if (std2.id & V4L2_STD_PAL)
+                       tun->flags |= VIDEO_TUNER_PAL;
+               if (std2.id & V4L2_STD_NTSC)
+                       tun->flags |= VIDEO_TUNER_NTSC;
+               if (std2.id & V4L2_STD_SECAM)
+                       tun->flags |= VIDEO_TUNER_SECAM;
+       }
 
-               if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
-                       aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
-               else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
-                       aud->mode = VIDEO_SOUND_STEREO;
-               else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
-                       aud->mode = VIDEO_SOUND_MONO;
-               break;
+       err = drv(inode, file, VIDIOC_G_STD, &sid);
+       if (err < 0)
+               dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
+       if (err == 0) {
+               if (sid & V4L2_STD_PAL)
+                       tun->mode = VIDEO_MODE_PAL;
+               if (sid & V4L2_STD_NTSC)
+                       tun->mode = VIDEO_MODE_NTSC;
+               if (sid & V4L2_STD_SECAM)
+                       tun->mode = VIDEO_MODE_SECAM;
        }
-       case VIDIOCSAUDIO: /*  set audio controls  */
-       {
-               struct video_audio      *aud = arg;
 
-               memset(&aud2,0,sizeof(aud2));
-               memset(&tun2,0,sizeof(tun2));
+       if (tun2.capability & V4L2_TUNER_CAP_LOW)
+               tun->flags |= VIDEO_TUNER_LOW;
+       if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+               tun->flags |= VIDEO_TUNER_STEREO_ON;
+       tun->signal = tun2.signal;
+done:
+       return err;
+}
 
-               aud2.index = aud->audio;
-               err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
-               if (err < 0) {
-                       dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
-                       break;
-               }
+static noinline int v4l1_compat_select_tuner(
+                                       struct video_tuner *tun,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_tuner       t;/*84 bytes on x86_64*/
+       memset(&t, 0, sizeof(t));
 
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
-                               aud->volume, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
-                               aud->bass, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
-                               aud->treble, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
-                               aud->balance, drv);
-               set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
-                               !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
-
-               err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
-               if (err < 0)
-                       dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
-               if (err == 0) {
-                       switch (aud->mode) {
-                       default:
-                       case VIDEO_SOUND_MONO:
-                       case VIDEO_SOUND_LANG1:
-                               tun2.audmode = V4L2_TUNER_MODE_MONO;
-                               break;
-                       case VIDEO_SOUND_STEREO:
-                               tun2.audmode = V4L2_TUNER_MODE_STEREO;
-                               break;
-                       case VIDEO_SOUND_LANG2:
-                               tun2.audmode = V4L2_TUNER_MODE_LANG2;
-                               break;
-                       }
-                       err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
-                       if (err < 0)
-                               dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
-               }
+       t.index = tun->tuner;
+
+       err = drv(inode, file, VIDIOC_S_INPUT, &t);
+       if (err < 0)
+               dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
+       return err;
+}
+
+static noinline int v4l1_compat_get_frequency(
+                                       unsigned long *freq,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_frequency   freq2;
+       memset(&freq2, 0, sizeof(freq2));
+
+       freq2.tuner = 0;
+       err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+       if (err < 0)
+               dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
+       if (0 == err)
+               *freq = freq2.frequency;
+       return err;
+}
+
+static noinline int v4l1_compat_set_frequency(
+                                       unsigned long *freq,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_frequency   freq2;
+       memset(&freq2, 0, sizeof(freq2));
+
+       drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+       freq2.frequency = *freq;
+       err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+       if (err < 0)
+               dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
+       return err;
+}
+
+static noinline int v4l1_compat_get_audio(
+                                       struct video_audio *aud,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err, i;
+       struct v4l2_queryctrl   qctrl2;
+       struct v4l2_audio       aud2;
+       struct v4l2_tuner       tun2;
+       memset(&aud2, 0, sizeof(aud2));
+
+       err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+       if (err < 0) {
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
+               goto done;
+       }
+       memcpy(aud->name, aud2.name,
+              min(sizeof(aud->name), sizeof(aud2.name)));
+       aud->name[sizeof(aud->name) - 1] = 0;
+       aud->audio = aud2.index;
+       aud->flags = 0;
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+       if (i >= 0) {
+               aud->volume = i;
+               aud->flags |= VIDEO_AUDIO_VOLUME;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+       if (i >= 0) {
+               aud->bass = i;
+               aud->flags |= VIDEO_AUDIO_BASS;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+       if (i >= 0) {
+               aud->treble = i;
+               aud->flags |= VIDEO_AUDIO_TREBLE;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+       if (i >= 0) {
+               aud->balance = i;
+               aud->flags |= VIDEO_AUDIO_BALANCE;
+       }
+       i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+       if (i >= 0) {
+               if (i)
+                       aud->flags |= VIDEO_AUDIO_MUTE;
+               aud->flags |= VIDEO_AUDIO_MUTABLE;
+       }
+       aud->step = 1;
+       qctrl2.id = V4L2_CID_AUDIO_VOLUME;
+       if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+           !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+               aud->step = qctrl2.step;
+       aud->mode = 0;
+
+       memset(&tun2, 0, sizeof(tun2));
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0) {
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
                err = 0;
-               break;
+               goto done;
        }
-       case VIDIOCMCAPTURE: /*  capture a frame  */
-       {
-               struct video_mmap       *mm = arg;
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               memset(&buf2,0,sizeof(buf2));
+       if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
+               aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+       else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+               aud->mode = VIDEO_SOUND_STEREO;
+       else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
+               aud->mode = VIDEO_SOUND_MONO;
+done:
+       return err;
+}
 
-               fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
+static noinline int v4l1_compat_set_audio(
+                                       struct video_audio *aud,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_audio       aud2;
+       struct v4l2_tuner       tun2;
+
+       memset(&aud2, 0, sizeof(aud2));
+       memset(&tun2, 0, sizeof(tun2));
+
+       aud2.index = aud->audio;
+       err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+       if (err < 0) {
+               dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
+               goto done;
+       }
+
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+                       aud->volume, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+                       aud->bass, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+                       aud->treble, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+                       aud->balance, drv);
+       set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+                       !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
+
+       err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+       if (err < 0)
+               dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
+       if (err == 0) {
+               switch (aud->mode) {
+               default:
+               case VIDEO_SOUND_MONO:
+               case VIDEO_SOUND_LANG1:
+                       tun2.audmode = V4L2_TUNER_MODE_MONO;
                        break;
-               }
-               if (mm->width   != fmt2->fmt.pix.width  ||
-                   mm->height  != fmt2->fmt.pix.height ||
-                   palette_to_pixelformat(mm->format) !=
-                   fmt2->fmt.pix.pixelformat)
-               {/* New capture format...  */
-                       fmt2->fmt.pix.width = mm->width;
-                       fmt2->fmt.pix.height = mm->height;
-                       fmt2->fmt.pix.pixelformat =
-                               palette_to_pixelformat(mm->format);
-                       fmt2->fmt.pix.field = V4L2_FIELD_ANY;
-                       fmt2->fmt.pix.bytesperline = 0;
-                       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-                       if (err < 0) {
-                               dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
-                               break;
-                       }
-               }
-               buf2.index = mm->frame;
-               buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
+               case VIDEO_SOUND_STEREO:
+                       tun2.audmode = V4L2_TUNER_MODE_STEREO;
                        break;
-               }
-               err = drv(inode, file, VIDIOC_QBUF, &buf2);
-               if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
+               case VIDEO_SOUND_LANG2:
+                       tun2.audmode = V4L2_TUNER_MODE_LANG2;
                        break;
                }
-               err = drv(inode, file, VIDIOC_STREAMON, &captype);
+               err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
                if (err < 0)
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
-               break;
+                       dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
        }
-       case VIDIOCSYNC: /*  wait for a frame  */
-       {
-               int                     *i = arg;
+       err = 0;
+done:
+       return err;
+}
 
-               memset(&buf2,0,sizeof(buf2));
-               buf2.index = *i;
-               buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-               if (err < 0) {
-                       /*  No such buffer */
-                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
-                       break;
-               }
-               if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
-                       /* Buffer is not mapped  */
-                       err = -EINVAL;
-                       break;
-               }
+static noinline int v4l1_compat_capture_frame(
+                                       struct video_mmap *mm,
+                                       struct inode *inode,
+                                       struct file *file,
+                                       v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       struct v4l2_buffer      buf;
+       struct v4l2_format      *fmt;
+
+       fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+       if (!fmt) {
+               err = -ENOMEM;
+               return err;
+       }
+       memset(&buf, 0, sizeof(buf));
 
-               /* make sure capture actually runs so we don't block forever */
-               err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_G_FMT, fmt);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       if (mm->width   != fmt->fmt.pix.width  ||
+           mm->height  != fmt->fmt.pix.height ||
+           palette_to_pixelformat(mm->format) !=
+           fmt->fmt.pix.pixelformat) {
+               /* New capture format...  */
+               fmt->fmt.pix.width = mm->width;
+               fmt->fmt.pix.height = mm->height;
+               fmt->fmt.pix.pixelformat =
+                       palette_to_pixelformat(mm->format);
+               fmt->fmt.pix.field = V4L2_FIELD_ANY;
+               fmt->fmt.pix.bytesperline = 0;
+               err = drv(inode, file, VIDIOC_S_FMT, fmt);
                if (err < 0) {
-                       dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
-                       break;
+                       dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
+                       goto done;
                }
+       }
+       buf.index = mm->frame;
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_QBUF, &buf);
+       if (err < 0) {
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       if (err < 0)
+               dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
+done:
+       kfree(fmt);
+       return err;
+}
 
-               /*  Loop as long as the buffer is queued, but not done  */
-               while ((buf2.flags &
-                       (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
-                      == V4L2_BUF_FLAG_QUEUED)
-               {
-                       err = poll_one(file);
-                       if (err < 0 ||  /* error or sleep was interrupted  */
-                           err == 0)   /* timeout? Shouldn't occur.  */
-                               break;
-                       err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
-                       if (err < 0)
-                               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
-               }
-               if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
-                       break;
-               do {
-                       err = drv(inode, file, VIDIOC_DQBUF, &buf2);
-                       if (err < 0)
-                               dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
-               } while (err == 0 && buf2.index != *i);
-               break;
+static noinline int v4l1_compat_sync(
+                               int *i,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       struct v4l2_buffer buf;
+       struct poll_wqueues *pwq;
+
+       memset(&buf, 0, sizeof(buf));
+       buf.index = *i;
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+       if (err < 0) {
+               /*  No such buffer */
+               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+               goto done;
+       }
+       if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
+               /* Buffer is not mapped  */
+               err = -EINVAL;
+               goto done;
        }
 
-       case VIDIOCGVBIFMT: /* query VBI data capture format */
-       {
-               struct vbi_format      *fmt = arg;
+       /* make sure capture actually runs so we don't block forever */
+       err = drv(inode, file, VIDIOC_STREAMON, &captype);
+       if (err < 0) {
+               dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
+               goto done;
+       }
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
+       pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
+       /*  Loop as long as the buffer is queued, but not done  */
+       while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
+                                               == V4L2_BUF_FLAG_QUEUED) {
+               err = poll_one(file, pwq);
+               if (err < 0 ||  /* error or sleep was interrupted  */
+                   err == 0)   /* timeout? Shouldn't occur.  */
                        break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+               if (err < 0)
+                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+       }
+       kfree(pwq);
+       if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
+               goto done;
+       do {
+               err = drv(inode, file, VIDIOC_DQBUF, &buf);
+               if (err < 0)
+                       dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
+       } while (err == 0 && buf.index != *i);
+done:
+       return err;
+}
 
-               err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
-                       break;
-               }
-               if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
-                       err = -EINVAL;
-                       break;
-               }
-               memset(fmt, 0, sizeof(*fmt));
-               fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
-               fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
-               fmt->sample_format    = VIDEO_PALETTE_RAW;
-               fmt->start[0]         = fmt2->fmt.vbi.start[0];
-               fmt->count[0]         = fmt2->fmt.vbi.count[0];
-               fmt->start[1]         = fmt2->fmt.vbi.start[1];
-               fmt->count[1]         = fmt2->fmt.vbi.count[1];
-               fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
-               break;
+static noinline int v4l1_compat_get_vbi_format(
+                               struct vbi_format *fmt,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format *fmt2;
+
+       fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+       if (!fmt2) {
+               err = -ENOMEM;
+               return err;
        }
-       case VIDIOCSVBIFMT:
-       {
-               struct vbi_format      *fmt = arg;
+       fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 
-               if (VIDEO_PALETTE_RAW != fmt->sample_format) {
-                       err = -EINVAL;
-                       break;
-               }
+       err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+       if (err < 0) {
+               dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+               goto done;
+       }
+       if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+               err = -EINVAL;
+               goto done;
+       }
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
+       fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
+       fmt->sample_format    = VIDEO_PALETTE_RAW;
+       fmt->start[0]         = fmt2->fmt.vbi.start[0];
+       fmt->count[0]         = fmt2->fmt.vbi.count[0];
+       fmt->start[1]         = fmt2->fmt.vbi.start[1];
+       fmt->count[1]         = fmt2->fmt.vbi.count[1];
+       fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
+done:
+       kfree(fmt2);
+       return err;
+}
 
-               fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
-               if (!fmt2) {
-                       err = -ENOMEM;
-                       break;
-               }
-               fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
-               fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
-               fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-               fmt2->fmt.vbi.start[0]         = fmt->start[0];
-               fmt2->fmt.vbi.count[0]         = fmt->count[0];
-               fmt2->fmt.vbi.start[1]         = fmt->start[1];
-               fmt2->fmt.vbi.count[1]         = fmt->count[1];
-               fmt2->fmt.vbi.flags            = fmt->flags;
-               err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
-               if (err < 0) {
-                       dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
-                       break;
-               }
+static noinline int v4l1_compat_set_vbi_format(
+                               struct vbi_format *fmt,
+                               struct inode *inode,
+                               struct file *file,
+                               v4l2_kioctl drv)
+{
+       int err;
+       struct v4l2_format      *fmt2 = NULL;
 
-               if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
-                   fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
-                   fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
-                   fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
-                   fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
-                   fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
-                   fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
-                   fmt2->fmt.vbi.flags            != fmt->flags) {
-                       err = -EINVAL;
-                       break;
-               }
-               err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-               if (err < 0)
-                       dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
-               break;
+       if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+               err = -EINVAL;
+               return err;
        }
 
+       fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+       if (!fmt2) {
+               err = -ENOMEM;
+               return err;
+       }
+       fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
+       fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
+       fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
+       fmt2->fmt.vbi.start[0]         = fmt->start[0];
+       fmt2->fmt.vbi.count[0]         = fmt->count[0];
+       fmt2->fmt.vbi.start[1]         = fmt->start[1];
+       fmt2->fmt.vbi.count[1]         = fmt->count[1];
+       fmt2->fmt.vbi.flags            = fmt->flags;
+       err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+       if (err < 0) {
+               dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+               goto done;
+       }
+
+       if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
+           fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
+           fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
+           fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
+           fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
+           fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
+           fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
+           fmt2->fmt.vbi.flags            != fmt->flags) {
+               err = -EINVAL;
+               goto done;
+       }
+       err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+       if (err < 0)
+               dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+done:
+       kfree(fmt2);
+       return err;
+}
+
+/*
+ *     This function is exported.
+ */
+int
+v4l_compat_translate_ioctl(struct inode         *inode,
+                          struct file          *file,
+                          int                  cmd,
+                          void                 *arg,
+                          v4l2_kioctl          drv)
+{
+       int err;
+
+       switch (cmd) {
+       case VIDIOCGCAP:        /* capability */
+               err = v4l1_compat_get_capabilities(arg, inode, file, drv);
+               break;
+       case VIDIOCGFBUF: /*  get frame buffer  */
+               err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
+               break;
+       case VIDIOCSFBUF: /*  set frame buffer  */
+               err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
+               break;
+       case VIDIOCGWIN: /*  get window or capture dimensions  */
+               err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
+               break;
+       case VIDIOCSWIN: /*  set window and/or capture dimensions  */
+               err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
+               break;
+       case VIDIOCCAPTURE: /*  turn on/off preview  */
+               err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
+               break;
+       case VIDIOCGCHAN: /*  get input information  */
+               err = v4l1_compat_get_input_info(arg, inode, file, drv);
+               break;
+       case VIDIOCSCHAN: /*  set input  */
+               err = v4l1_compat_set_input(arg, inode, file, drv);
+               break;
+       case VIDIOCGPICT: /*  get tone controls & partial capture format  */
+               err = v4l1_compat_get_picture(arg, inode, file, drv);
+               break;
+       case VIDIOCSPICT: /*  set tone controls & partial capture format  */
+               err = v4l1_compat_set_picture(arg, inode, file, drv);
+               break;
+       case VIDIOCGTUNER: /*  get tuner information  */
+               err = v4l1_compat_get_tuner(arg, inode, file, drv);
+               break;
+       case VIDIOCSTUNER: /*  select a tuner input  */
+               err = v4l1_compat_select_tuner(arg, inode, file, drv);
+               break;
+       case VIDIOCGFREQ: /*  get frequency  */
+               err = v4l1_compat_get_frequency(arg, inode, file, drv);
+               break;
+       case VIDIOCSFREQ: /*  set frequency  */
+               err = v4l1_compat_set_frequency(arg, inode, file, drv);
+               break;
+       case VIDIOCGAUDIO: /*  get audio properties/controls  */
+               err = v4l1_compat_get_audio(arg, inode, file, drv);
+               break;
+       case VIDIOCSAUDIO: /*  set audio controls  */
+               err = v4l1_compat_set_audio(arg, inode, file, drv);
+               break;
+       case VIDIOCMCAPTURE: /*  capture a frame  */
+               err = v4l1_compat_capture_frame(arg, inode, file, drv);
+               break;
+       case VIDIOCSYNC: /*  wait for a frame  */
+               err = v4l1_compat_sync(arg, inode, file, drv);
+               break;
+       case VIDIOCGVBIFMT: /* query VBI data capture format */
+               err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
+               break;
+       case VIDIOCSVBIFMT:
+               err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
+               break;
        default:
                err = -ENOIOCTLCMD;
                break;
        }
 
-       kfree(cap2);
-       kfree(fmt2);
        return err;
 }
-
 EXPORT_SYMBOL(v4l_compat_translate_ioctl);
 
 /*
index eab79ffdf56a882529113c0e25623d0c5941ab1c..fc51e4918bbf790d05ee8d93160a31ddd994aefb 100644 (file)
@@ -64,32 +64,25 @@ void *videobuf_alloc(struct videobuf_queue *q)
        return vb;
 }
 
+#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
+                               vb->state != VIDEOBUF_QUEUED)
 int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
 {
-       int retval = 0;
-       DECLARE_WAITQUEUE(wait, current);
-
        MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
-       add_wait_queue(&vb->done, &wait);
-       while (vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) {
-               if (non_blocking) {
-                       retval = -EAGAIN;
-                       break;
-               }
-               set_current_state(intr  ? TASK_INTERRUPTIBLE
-                                       : TASK_UNINTERRUPTIBLE);
-               if (vb->state == VIDEOBUF_ACTIVE ||
-                   vb->state == VIDEOBUF_QUEUED)
-                       schedule();
-               set_current_state(TASK_RUNNING);
-               if (intr && signal_pending(current)) {
-                       dprintk(1, "buffer waiton: -EINTR\n");
-                       retval = -EINTR;
-                       break;
-               }
+
+       if (non_blocking) {
+               if (WAITON_CONDITION)
+                       return 0;
+               else
+                       return -EAGAIN;
        }
-       remove_wait_queue(&vb->done, &wait);
-       return retval;
+
+       if (intr)
+               return wait_event_interruptible(vb->done, WAITON_CONDITION);
+       else
+               wait_event(vb->done, WAITON_CONDITION);
+
+       return 0;
 }
 
 int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
@@ -98,29 +91,22 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
        MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
-       /* This is required to avoid OOPS on some cases,
-          since mmap_mapper() method should be called before _iolock.
-          On some cases, the mmap_mapper() is called only after scheduling.
-        */
-       if (vb->memory == V4L2_MEMORY_MMAP) {
-               wait_event_timeout(vb->done, q->is_mmapped,
-                                  msecs_to_jiffies(100));
-               if (!q->is_mmapped) {
-                       printk(KERN_ERR
-                              "Error: mmap_mapper() never called!\n");
-                       return -EINVAL;
-               }
-       }
-
        return CALL(q, iolock, q, vb, fbuf);
 }
 
+void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
+                          struct videobuf_buffer *buf)
+{
+       return CALL(q, vmalloc, buf);
+}
+EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
+
 /* --------------------------------------------------------------------- */
 
 
 void videobuf_queue_core_init(struct videobuf_queue *q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -144,10 +130,14 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
        BUG_ON(!q->ops->buf_queue);
        BUG_ON(!q->ops->buf_release);
 
+       /* Lock is mandatory for queue_cancel to work */
+       BUG_ON(!irqlock);
+
        /* Having implementations for abstract methods are mandatory */
        BUG_ON(!q->int_ops);
 
        mutex_init(&q->vb_lock);
+       init_waitqueue_head(&q->wait);
        INIT_LIST_HEAD(&q->stream);
 }
 
@@ -195,19 +185,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
        unsigned long flags = 0;
        int i;
 
+       q->streaming = 0;
+       q->reading  = 0;
+       wake_up_interruptible_sync(&q->wait);
+
        /* remove queued buffers from list */
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                if (NULL == q->bufs[i])
                        continue;
                if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
                        list_del(&q->bufs[i]->queue);
                        q->bufs[i]->state = VIDEOBUF_ERROR;
+                       wake_up_all(&q->bufs[i]->done);
                }
        }
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
 
        /* free all buffers + clear queue */
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -563,14 +556,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
 
        list_add_tail(&buf->stream, &q->stream);
        if (q->streaming) {
-               if (q->irqlock)
-                       spin_lock_irqsave(q->irqlock, flags);
+               spin_lock_irqsave(q->irqlock, flags);
                q->ops->buf_queue(q, buf);
-               if (q->irqlock)
-                       spin_unlock_irqrestore(q->irqlock, flags);
+               spin_unlock_irqrestore(q->irqlock, flags);
        }
        dprintk(1, "qbuf: succeded\n");
        retval = 0;
+       wake_up_interruptible_sync(&q->wait);
 
  done:
        mutex_unlock(&q->vb_lock);
@@ -581,35 +573,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
        return retval;
 }
 
-int videobuf_dqbuf(struct videobuf_queue *q,
-              struct v4l2_buffer *b, int nonblocking)
+
+/* Locking: Caller holds q->vb_lock */
+static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
 {
-       struct videobuf_buffer *buf;
        int retval;
 
-       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
-
-       mutex_lock(&q->vb_lock);
-       retval = -EBUSY;
-       if (q->reading) {
-               dprintk(1, "dqbuf: Reading running...\n");
-               goto done;
-       }
-       retval = -EINVAL;
-       if (b->type != q->type) {
-               dprintk(1, "dqbuf: Wrong type.\n");
+checks:
+       if (!q->streaming) {
+               dprintk(1, "next_buffer: Not streaming\n");
+               retval = -EINVAL;
                goto done;
        }
+
        if (list_empty(&q->stream)) {
-               dprintk(1, "dqbuf: stream running\n");
-               goto done;
+               if (noblock) {
+                       retval = -EAGAIN;
+                       dprintk(2, "next_buffer: no buffers to dequeue\n");
+                       goto done;
+               } else {
+                       dprintk(2, "next_buffer: waiting on buffer\n");
+
+                       /* Drop lock to avoid deadlock with qbuf */
+                       mutex_unlock(&q->vb_lock);
+
+                       /* Checking list_empty and streaming is safe without
+                        * locks because we goto checks to validate while
+                        * holding locks before proceeding */
+                       retval = wait_event_interruptible(q->wait,
+                               !list_empty(&q->stream) || !q->streaming);
+                       mutex_lock(&q->vb_lock);
+
+                       if (retval)
+                               goto done;
+
+                       goto checks;
+               }
        }
+
+       retval = 0;
+
+done:
+       return retval;
+}
+
+
+/* Locking: Caller holds q->vb_lock */
+static int stream_next_buffer(struct videobuf_queue *q,
+                       struct videobuf_buffer **vb, int nonblocking)
+{
+       int retval;
+       struct videobuf_buffer *buf = NULL;
+
+       retval = stream_next_buffer_check_queue(q, nonblocking);
+       if (retval)
+               goto done;
+
        buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
        retval = videobuf_waiton(buf, nonblocking, 1);
+       if (retval < 0)
+               goto done;
+
+       *vb = buf;
+done:
+       return retval;
+}
+
+int videobuf_dqbuf(struct videobuf_queue *q,
+              struct v4l2_buffer *b, int nonblocking)
+{
+       struct videobuf_buffer *buf = NULL;
+       int retval;
+
+       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+
+       mutex_lock(&q->vb_lock);
+
+       retval = stream_next_buffer(q, &buf, nonblocking);
        if (retval < 0) {
-               dprintk(1, "dqbuf: waiton returned %d\n", retval);
+               dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
                goto done;
        }
+
        switch (buf->state) {
        case VIDEOBUF_ERROR:
                dprintk(1, "dqbuf: state is error\n");
@@ -650,14 +695,13 @@ int videobuf_streamon(struct videobuf_queue *q)
        if (q->streaming)
                goto done;
        q->streaming = 1;
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        list_for_each_entry(buf, &q->stream, stream)
                if (buf->state == VIDEOBUF_PREPARED)
                        q->ops->buf_queue(q, buf);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
 
+       wake_up_interruptible_sync(&q->wait);
  done:
        mutex_unlock(&q->vb_lock);
        return retval;
@@ -670,7 +714,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
                return -EINVAL;
 
        videobuf_queue_cancel(q);
-       q->streaming = 0;
 
        return 0;
 }
@@ -712,11 +755,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
                goto done;
 
        /* start capture & wait */
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        q->ops->buf_queue(q, q->read_buf);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
        retval = videobuf_waiton(q->read_buf, 0, 0);
        if (0 == retval) {
                CALL(q, sync, q, q->read_buf);
@@ -740,14 +781,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
 {
        enum v4l2_field field;
        unsigned long flags = 0;
-       unsigned size, nbufs;
+       unsigned size = 0, nbufs = 1;
        int retval;
 
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
        mutex_lock(&q->vb_lock);
 
-       nbufs = 1; size = 0;
        q->ops->buf_setup(q, &nbufs, &size);
 
        if (NULL == q->read_buf  &&
@@ -778,12 +818,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
                        q->read_buf = NULL;
                        goto done;
                }
-               if (q->irqlock)
-                       spin_lock_irqsave(q->irqlock, flags);
 
+               spin_lock_irqsave(q->irqlock, flags);
                q->ops->buf_queue(q, q->read_buf);
-               if (q->irqlock)
-                       spin_unlock_irqrestore(q->irqlock, flags);
+               spin_unlock_irqrestore(q->irqlock, flags);
+
                q->read_off = 0;
        }
 
@@ -849,12 +888,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
                        return err;
                list_add_tail(&q->bufs[i]->stream, &q->stream);
        }
-       if (q->irqlock)
-               spin_lock_irqsave(q->irqlock, flags);
+       spin_lock_irqsave(q->irqlock, flags);
        for (i = 0; i < count; i++)
                q->ops->buf_queue(q, q->bufs[i]);
-       if (q->irqlock)
-               spin_unlock_irqrestore(q->irqlock, flags);
+       spin_unlock_irqrestore(q->irqlock, flags);
        q->reading = 1;
        return 0;
 }
@@ -863,7 +900,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
 {
        int i;
 
-
        videobuf_queue_cancel(q);
        __videobuf_mmap_free(q);
        INIT_LIST_HEAD(&q->stream);
@@ -874,7 +910,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
                q->bufs[i] = NULL;
        }
        q->read_buf = NULL;
-       q->reading  = 0;
 
 }
 
@@ -919,7 +954,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
 
        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
 
-       dprintk(2, "%s\n", __FUNCTION__);
+       dprintk(2, "%s\n", __func__);
        mutex_lock(&q->vb_lock);
        retval = -EBUSY;
        if (q->streaming)
@@ -968,11 +1003,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
                if (q->read_off == q->read_buf->size) {
                        list_add_tail(&q->read_buf->stream,
                                      &q->stream);
-                       if (q->irqlock)
-                               spin_lock_irqsave(q->irqlock, flags);
+                       spin_lock_irqsave(q->irqlock, flags);
                        q->ops->buf_queue(q, q->read_buf);
-                       if (q->irqlock)
-                               spin_unlock_irqrestore(q->irqlock, flags);
+                       spin_unlock_irqrestore(q->irqlock, flags);
                        q->read_buf = NULL;
                }
                if (retval < 0)
index 53fed4b74ce966be1a43271fd4ff57ab469e92df..03a7b946bd5448b4b5e471836fd8469bdfc492c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * helper functions for PCI DMA video4linux capture buffers
+ * helper functions for SG DMA video4linux capture buffers
  *
  * The functions expect the hardware being able to scatter gatter
  * (i.e. the buffers are not linear in physical memory, but fragmented
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
        { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 
-MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
+MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
 
@@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
 
 struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
 {
-       struct videbuf_pci_sg_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
        return &mem->dma;
 }
@@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 
        dma->direction = direction;
        switch (dma->direction) {
-       case PCI_DMA_FROMDEVICE: rw = READ;  break;
-       case PCI_DMA_TODEVICE:   rw = WRITE; break;
-       default:                 BUG();
+       case DMA_FROM_DEVICE:
+               rw = READ;
+               break;
+       case DMA_TO_DEVICE:
+               rw = WRITE;
+               break;
+       default:
+               BUG();
        }
 
        first = (data          & PAGE_MASK) >> PAGE_SHIFT;
@@ -157,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
        dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
                data,size,dma->nr_pages);
 
-       dma->varea = (void *) data;
-
-
        err = get_user_pages(current,current->mm,
                             data & PAGE_MASK, dma->nr_pages,
                             rw == READ, 1, /* force */
@@ -216,10 +218,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
        return 0;
 }
 
-int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
        MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
        BUG_ON(0 == dma->nr_pages);
 
@@ -245,11 +245,11 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
                return -ENOMEM;
        }
        if (!dma->bus_addr) {
-               dma->sglen = pci_map_sg(dev,dma->sglist,
+               dma->sglen = dma_map_sg(q->dev, dma->sglist,
                                        dma->nr_pages, dma->direction);
                if (0 == dma->sglen) {
                        printk(KERN_WARNING
-                              "%s: videobuf_map_sg failed\n",__FUNCTION__);
+                              "%s: videobuf_map_sg failed\n",__func__);
                        kfree(dma->sglist);
                        dma->sglist = NULL;
                        dma->sglen = 0;
@@ -259,26 +259,22 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
        return 0;
 }
 
-int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
+int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
-       MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+       MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
        BUG_ON(!dma->sglen);
 
-       pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction);
+       dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction);
        return 0;
 }
 
 int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
 {
-       void                   *dev=q->dev;
-
-       MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+       MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
        if (!dma->sglen)
                return 0;
 
-       pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction);
+       dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
 
        kfree(dma->sglist);
        dma->sglist = NULL;
@@ -301,33 +297,32 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
 
        vfree(dma->vmalloc);
        dma->vmalloc = NULL;
-       dma->varea = NULL;
 
        if (dma->bus_addr) {
                dma->bus_addr = 0;
        }
-       dma->direction = PCI_DMA_NONE;
+       dma->direction = DMA_NONE;
        return 0;
 }
 
 /* --------------------------------------------------------------------- */
 
-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
 
-       q.dev=pci;
+       q.dev = dev;
 
-       return (videobuf_dma_map(&q,dma));
+       return videobuf_dma_map(&q, dma);
 }
 
-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
 
-       q.dev=pci;
+       q.dev = dev;
 
-       return (videobuf_dma_unmap(&q,dma));
+       return videobuf_dma_unmap(&q, dma);
 }
 
 /* --------------------------------------------------------------------- */
@@ -347,7 +342,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
        struct videobuf_queue *q = map->q;
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        int i;
 
        dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
@@ -409,18 +404,18 @@ static struct vm_operations_struct videobuf_vm_ops =
 };
 
 /* ---------------------------------------------------------------------
- * PCI handlers for the generic methods
+ * SG handlers for the generic methods
  */
 
 /* Allocated area consists on 3 parts:
        struct video_buffer
        struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
-       struct videobuf_pci_sg_memory
+       struct videobuf_dma_sg_memory
  */
 
 static void *__videobuf_alloc(size_t size)
 {
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        struct videobuf_buffer *vb;
 
        vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
@@ -431,22 +426,32 @@ static void *__videobuf_alloc(size_t size)
        videobuf_dma_init(&mem->dma);
 
        dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
-               __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+               __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
                mem,(long)sizeof(*mem));
 
        return vb;
 }
 
+static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf)
+{
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
+
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+       return mem->dma.vmalloc;
+}
+
 static int __videobuf_iolock (struct videobuf_queue* q,
                              struct videobuf_buffer *vb,
                              struct v4l2_framebuffer *fbuf)
 {
        int err,pages;
        dma_addr_t bus;
-       struct videbuf_pci_sg_memory *mem=vb->priv;
+       struct videobuf_dma_sg_memory *mem = vb->priv;
        BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
 
        switch (vb->memory) {
        case V4L2_MEMORY_MMAP:
@@ -455,14 +460,14 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                        /* no userspace addr -- kernel bounce buffer */
                        pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
                        err = videobuf_dma_init_kernel( &mem->dma,
-                                                       PCI_DMA_FROMDEVICE,
+                                                       DMA_FROM_DEVICE,
                                                        pages );
                        if (0 != err)
                                return err;
                } else if (vb->memory == V4L2_MEMORY_USERPTR) {
                        /* dma directly to userspace */
                        err = videobuf_dma_init_user( &mem->dma,
-                                                     PCI_DMA_FROMDEVICE,
+                                                     DMA_FROM_DEVICE,
                                                      vb->baddr,vb->bsize );
                        if (0 != err)
                                return err;
@@ -473,7 +478,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                        locking inversion, so don't take it here */
 
                        err = videobuf_dma_init_user_locked(&mem->dma,
-                                                     PCI_DMA_FROMDEVICE,
+                                                     DMA_FROM_DEVICE,
                                                      vb->baddr, vb->bsize);
                        if (0 != err)
                                return err;
@@ -490,7 +495,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                 */
                bus   = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
                pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
-               err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
+               err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE,
                                                bus, pages);
                if (0 != err)
                        return err;
@@ -498,7 +503,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
        default:
                BUG();
        }
-       err = videobuf_dma_map(q,&mem->dma);
+       err = videobuf_dma_map(q, &mem->dma);
        if (0 != err)
                return err;
 
@@ -508,8 +513,8 @@ static int __videobuf_iolock (struct videobuf_queue* q,
 static int __videobuf_sync(struct videobuf_queue *q,
                           struct videobuf_buffer *buf)
 {
-       struct videbuf_pci_sg_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        return  videobuf_dma_sync(q,&mem->dma);
@@ -532,7 +537,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                         struct vm_area_struct *vma)
 {
-       struct videbuf_pci_sg_memory *mem;
+       struct videobuf_dma_sg_memory *mem;
        struct videobuf_mapping *map;
        unsigned int first,last,size,i;
        int retval;
@@ -547,12 +552,20 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                goto done;
        }
 
+       /* This function maintains backwards compatibility with V4L1 and will
+        * map more than one buffer if the vma length is equal to the combined
+        * size of multiple buffers than it will map them together.  See
+        * VIDIOCGMBUF in the v4l spec
+        *
+        * TODO: Allow drivers to specify if they support this mode
+        */
+
        /* look for first buffer to map */
        for (first = 0; first < VIDEO_MAX_FRAME; first++) {
                if (NULL == q->bufs[first])
                        continue;
                mem=q->bufs[first]->priv;
-               BUG_ON (!mem);
+               BUG_ON(!mem);
                MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
                if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
@@ -591,10 +604,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
        if (NULL == map)
                goto done;
-       for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
+
+       size = 0;
+       for (i = first; i <= last; i++) {
+               if (NULL == q->bufs[i])
+                       continue;
                q->bufs[i]->map   = map;
                q->bufs[i]->baddr = vma->vm_start + size;
+               size += q->bufs[i]->bsize;
        }
+
        map->count    = 1;
        map->start    = vma->vm_start;
        map->end      = vma->vm_end;
@@ -615,8 +634,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
                                char __user *data, size_t count,
                                int nonblocking )
 {
-       struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        /* copy to userspace */
@@ -634,8 +653,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
                                int vbihack, int nonblocking )
 {
        unsigned int  *fc;
-       struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
+       BUG_ON(!mem);
        MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
 
        if (vbihack) {
@@ -658,7 +677,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
        return count;
 }
 
-static struct videobuf_qtype_ops pci_ops = {
+static struct videobuf_qtype_ops sg_ops = {
        .magic        = MAGIC_QTYPE_OPS,
 
        .alloc        = __videobuf_alloc,
@@ -668,23 +687,24 @@ static struct videobuf_qtype_ops pci_ops = {
        .mmap_mapper  = __videobuf_mmap_mapper,
        .video_copy_to_user = __videobuf_copy_to_user,
        .copy_stream  = __videobuf_copy_stream,
+       .vmalloc      = __videobuf_to_vmalloc,
 };
 
-void *videobuf_pci_alloc (size_t size)
+void *videobuf_sg_alloc(size_t size)
 {
        struct videobuf_queue q;
 
        /* Required to make generic handler to call __videobuf_alloc */
-       q.int_ops=&pci_ops;
+       q.int_ops = &sg_ops;
 
-       q.msize=size;
+       q.msize = size;
 
-       return videobuf_alloc (&q);
+       return videobuf_alloc(&q);
 }
 
-void videobuf_queue_pci_init(struct videobuf_queue* q,
+void videobuf_queue_sg_init(struct videobuf_queue* q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -692,7 +712,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
                         void *priv)
 {
        videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
-                                priv, &pci_ops);
+                                priv, &sg_ops);
 }
 
 /* --------------------------------------------------------------------- */
@@ -709,11 +729,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync);
 EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
 EXPORT_SYMBOL_GPL(videobuf_dma_free);
 
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
-EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
+EXPORT_SYMBOL_GPL(videobuf_sg_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap);
+EXPORT_SYMBOL_GPL(videobuf_sg_alloc);
 
-EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
+EXPORT_SYMBOL_GPL(videobuf_queue_sg_init);
 
 /*
  * Local variables:
index b73aba65d21d00850e7604fbb6b408c7a62879ce..6e4d73ec6855f274684df7e4b80cea0d4b9b0bd4 100644 (file)
 #include <linux/fs.h>
 #include <linux/kthread.h>
 #include <linux/file.h>
+
 #include <linux/freezer.h>
 
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-core.h>
 #include <media/videobuf-dvb.h>
 
 /* ------------------------------------------------------------------ */
@@ -30,7 +31,7 @@
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int debug = 0;
+static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,"enable debug messages");
 
@@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data)
        struct videobuf_buffer *buf;
        unsigned long flags;
        int err;
-       struct videobuf_dmabuf *dma;
+       void *outp;
 
        dprintk("dvb thread started\n");
        set_freezable();
@@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data)
                try_to_freeze();
 
                /* feed buffer data to demux */
-               dma=videobuf_to_dma(buf);
+               outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf);
+
                if (buf->state == VIDEOBUF_DONE)
-                       dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
+                       dvb_dmx_swfilter(&dvb->demux, outp,
                                         buf->size);
 
                /* requeue buffer */
@@ -138,14 +140,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
                          void *adapter_priv,
-                         struct device *device)
+                         struct device *device,
+                         short *adapter_nr)
 {
        int result;
 
        mutex_init(&dvb->lock);
 
        /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
+       result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
+                                     adapter_nr);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
                       dvb->name, result);
index 5266ecc91dababf0aea005e376b045ea4351a251..c91e1d8e38025d32c292d888cac3feeb20103d6d 100644 (file)
@@ -33,7 +33,7 @@
 #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
        { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0644);
 
 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
@@ -57,20 +57,26 @@ videobuf_vm_open(struct vm_area_struct *vma)
        map->count++;
 }
 
-static void
-videobuf_vm_close(struct vm_area_struct *vma)
+static void videobuf_vm_close(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
        struct videobuf_queue *q = map->q;
        int i;
 
-       dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
-               map->count,vma->vm_start,vma->vm_end);
+       dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
+               map->count, vma->vm_start, vma->vm_end);
 
        map->count--;
        if (0 == map->count) {
-               dprintk(1,"munmap %p q=%p\n",map,q);
+               struct videobuf_vmalloc_memory *mem;
+
+               dprintk(1, "munmap %p q=%p\n", map, q);
                mutex_lock(&q->vb_lock);
+
+               /* We need first to cancel streams, before unmapping */
+               if (q->streaming)
+                       videobuf_queue_cancel(q);
+
                for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                        if (NULL == q->bufs[i])
                                continue;
@@ -78,14 +84,35 @@ videobuf_vm_close(struct vm_area_struct *vma)
                        if (q->bufs[i]->map != map)
                                continue;
 
-                       q->ops->buf_release(q,q->bufs[i]);
+                       mem = q->bufs[i]->priv;
+                       if (mem) {
+                               /* This callback is called only if kernel has
+                                  allocated memory and this memory is mmapped.
+                                  In this case, memory should be freed,
+                                  in order to do memory unmap.
+                                */
+
+                               MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+                               /* vfree is not atomic - can't be
+                                  called with IRQ's disabled
+                                */
+                               dprintk(1, "%s: buf[%d] freeing (%p)\n",
+                                       __func__, i, mem->vmalloc);
+
+                               vfree(mem->vmalloc);
+                               mem->vmalloc = NULL;
+                       }
 
                        q->bufs[i]->map   = NULL;
                        q->bufs[i]->baddr = 0;
                }
-               mutex_unlock(&q->vb_lock);
+
                kfree(map);
+
+               mutex_unlock(&q->vb_lock);
        }
+
        return;
 }
 
@@ -102,7 +129,7 @@ static struct vm_operations_struct videobuf_vm_ops =
 /* Allocated area consists on 3 parts:
        struct video_buffer
        struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
-       struct videobuf_pci_sg_memory
+       struct videobuf_dma_sg_memory
  */
 
 static void *__videobuf_alloc(size_t size)
@@ -116,7 +143,7 @@ static void *__videobuf_alloc(size_t size)
        mem->magic=MAGIC_VMAL_MEM;
 
        dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
-               __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+               __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
                mem,(long)sizeof(*mem));
 
        return vb;
@@ -126,45 +153,74 @@ static int __videobuf_iolock (struct videobuf_queue* q,
                              struct videobuf_buffer *vb,
                              struct v4l2_framebuffer *fbuf)
 {
+       struct videobuf_vmalloc_memory *mem = vb->priv;
        int pages;
-       struct videobuf_vmalloc_memory *mem=vb->priv;
 
        BUG_ON(!mem);
 
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
-       pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+       switch (vb->memory) {
+       case V4L2_MEMORY_MMAP:
+               dprintk(1, "%s memory method MMAP\n", __func__);
 
-       /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
-       if ((vb->memory != V4L2_MEMORY_MMAP) &&
-                               (vb->memory != V4L2_MEMORY_USERPTR) ) {
-               printk(KERN_ERR "Method currently unsupported.\n");
-               return -EINVAL;
-       }
+               /* All handling should be done by __videobuf_mmap_mapper() */
+               if (!mem->vmalloc) {
+                       printk(KERN_ERR "memory is not alloced/mmapped.\n");
+                       return -EINVAL;
+               }
+               break;
+       case V4L2_MEMORY_USERPTR:
+               pages = PAGE_ALIGN(vb->size);
 
-       /* FIXME: should be tested with kernel mmap mem */
-       mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
-       if (NULL == mem->vmalloc) {
-               printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
-               return -ENOMEM;
-       }
+               dprintk(1, "%s memory method USERPTR\n", __func__);
 
-       dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
-                               (unsigned long)mem->vmalloc,
-                               pages << PAGE_SHIFT);
+#if 1
+               if (vb->baddr) {
+                       printk(KERN_ERR "USERPTR is currently not supported\n");
+                       return -EINVAL;
+               }
+#endif
 
-       /* It seems that some kernel versions need to do remap *after*
-          the mmap() call
-        */
-       if (mem->vma) {
-               int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0);
-               kfree(mem->vma);
-               mem->vma=NULL;
-               if (retval<0) {
-                       dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n",
-                               mem->vmalloc,retval);
-                       return retval;
+               /* The only USERPTR currently supported is the one needed for
+                  read() method.
+                */
+
+               mem->vmalloc = vmalloc_user(pages);
+               if (!mem->vmalloc) {
+                       printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+                       return -ENOMEM;
+               }
+               dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+                       mem->vmalloc, pages);
+
+#if 0
+               int rc;
+               /* Kernel userptr is used also by read() method. In this case,
+                  there's no need to remap, since data will be copied to user
+                */
+               if (!vb->baddr)
+                       return 0;
+
+               /* FIXME: to properly support USERPTR, remap should occur.
+                  The code bellow won't work, since mem->vma = NULL
+                */
+               /* Try to remap memory */
+               rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
+               if (rc < 0) {
+                       printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
+                       return -ENOMEM;
                }
+#endif
+
+               break;
+       case V4L2_MEMORY_OVERLAY:
+       default:
+               dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
+
+               /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+               printk(KERN_ERR "Memory method currently unsupported.\n");
+               return -EINVAL;
        }
 
        return 0;
@@ -180,6 +236,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
 {
        unsigned int i;
 
+       dprintk(1, "%s\n", __func__);
        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                if (q->bufs[i]) {
                        if (q->bufs[i]->map)
@@ -196,10 +253,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        struct videobuf_vmalloc_memory *mem;
        struct videobuf_mapping *map;
        unsigned int first;
-       int retval;
+       int retval, pages;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 
-       if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+       dprintk(1, "%s\n", __func__);
+       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
                return -EINVAL;
 
        /* look for first buffer to map */
@@ -219,46 +277,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        }
 
        /* create mapping + update buffer list */
-       map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+       map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
        if (NULL == map)
                return -ENOMEM;
 
+       q->bufs[first]->map = map;
        map->start = vma->vm_start;
        map->end   = vma->vm_end;
        map->q     = q;
 
        q->bufs[first]->baddr = vma->vm_start;
 
-       vma->vm_ops          = &videobuf_vm_ops;
-       vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
-       vma->vm_private_data = map;
+       mem = q->bufs[first]->priv;
+       BUG_ON(!mem);
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
-       mem=q->bufs[first]->priv;
-       BUG_ON (!mem);
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
+       mem->vmalloc = vmalloc_user(pages);
+       if (!mem->vmalloc) {
+               printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+               goto error;
+       }
+       dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+               mem->vmalloc, pages);
 
        /* Try to remap memory */
-       retval=remap_vmalloc_range(vma, mem->vmalloc,0);
-       if (retval<0) {
-               dprintk(1,"mmap: postponing remap_vmalloc_range\n");
-
-               mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL);
-               if (!mem->vma) {
-                       kfree(map);
-                       q->bufs[first]->map=NULL;
-                       return -ENOMEM;
-               }
-               memcpy(mem->vma,vma,sizeof(*vma));
+       retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
+       if (retval < 0) {
+               printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
+               vfree(mem->vmalloc);
+               goto error;
        }
 
+       vma->vm_ops          = &videobuf_vm_ops;
+       vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
+       vma->vm_private_data = map;
+
        dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
-               map,q,vma->vm_start,vma->vm_end,
+               map, q, vma->vm_start, vma->vm_end,
                (long int) q->bufs[first]->bsize,
-               vma->vm_pgoff,first);
+               vma->vm_pgoff, first);
 
        videobuf_vm_open(vma);
 
-       return (0);
+       return 0;
+
+error:
+       mem = NULL;
+       kfree(map);
+       return -ENOMEM;
 }
 
 static int __videobuf_copy_to_user ( struct videobuf_queue *q,
@@ -320,6 +387,7 @@ static struct videobuf_qtype_ops qops = {
        .mmap_mapper  = __videobuf_mmap_mapper,
        .video_copy_to_user = __videobuf_copy_to_user,
        .copy_stream  = __videobuf_copy_stream,
+       .vmalloc      = videobuf_to_vmalloc,
 };
 
 void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
@@ -349,13 +417,24 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
 
 void videobuf_vmalloc_free (struct videobuf_buffer *buf)
 {
-       struct videobuf_vmalloc_memory *mem=buf->priv;
-       BUG_ON (!mem);
+       struct videobuf_vmalloc_memory *mem = buf->priv;
 
-       MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+       /* mmapped memory can't be freed here, otherwise mmapped region
+          would be released, while still needed. In this case, the memory
+          release should happen inside videobuf_vm_close().
+          So, it should free memory only if the memory were allocated for
+          read() operation.
+        */
+       if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
+               return;
+
+       if (!mem)
+               return;
+
+       MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
 
        vfree(mem->vmalloc);
-       mem->vmalloc=NULL;
+       mem->vmalloc = NULL;
 
        return;
 }
index 87951ec8254f47cd8be33557237cd7bedf54d902..cf24956f3204272cd6b9eeebb5ecf7b8c20ffeaa 100644 (file)
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #endif
 
 #include "videocodec.h"
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
@@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec)
 }
 
 #ifdef CONFIG_PROC_FS
-/* ============ */
-/* procfs stuff */
-/* ============ */
-
-static char *videocodec_buf = NULL;
-static int videocodec_bufsize = 0;
-
-static int
-videocodec_build_table (void)
+static int proc_videocodecs_show(struct seq_file *m, void *v)
 {
        struct codec_list *h = codeclist_top;
        struct attached_list *a;
-       int i = 0, size;
-
-       // sum up amount of slaves plus their attached masters
-       while (h) {
-               i += h->attached + 1;
-               h = h->next;
-       }
-#define LINESIZE 100
-       size = LINESIZE * (i + 1);
 
-       dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
-               size);
-
-       kfree(videocodec_buf);
-       videocodec_buf = kmalloc(size, GFP_KERNEL);
-
-       if (!videocodec_buf)
-               return 0;
-
-       i = 0;
-       i += scnprintf(videocodec_buf + i, size - 1,
-                     "<S>lave or attached <M>aster name  type flags    magic    ");
-       i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
+       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
+       seq_printf(m, "(connected as)\n");
 
        h = codeclist_top;
        while (h) {
-               if (i > (size - LINESIZE))
-                       break;  // security check
-               i += scnprintf(videocodec_buf + i, size -i -1,
-                             "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+               seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
                              h->codec->name, h->codec->type,
                              h->codec->flags, h->codec->magic);
                a = h->list;
                while (a) {
-                       if (i > (size - LINESIZE))
-                               break;  // security check
-                       i += scnprintf(videocodec_buf + i, size -i -1,
-                                     "M %32s %04x %08lx %08lx (%s)\n",
+                       seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
                                      a->codec->master_data->name,
                                      a->codec->master_data->type,
                                      a->codec->master_data->flags,
@@ -380,54 +347,21 @@ videocodec_build_table (void)
                h = h->next;
        }
 
-       return i;
+       return 0;
 }
 
-//The definition:
-//typedef int (read_proc_t)(char *page, char **start, off_t off,
-//                          int count, int *eof, void *data);
-
-static int
-videocodec_info (char  *buffer,
-                char **buffer_location,
-                off_t  offset,
-                int    buffer_length,
-                int   *eof,
-                void  *data)
+static int proc_videocodecs_open(struct inode *inode, struct file *file)
 {
-       int size;
-
-       dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n",
-               offset, buffer_length, videocodec_bufsize);
-
-       if (offset == 0) {
-               videocodec_bufsize = videocodec_build_table();
-       }
-       if ((offset < 0) || (offset >= videocodec_bufsize)) {
-               dprintk(4,
-                       "videocodec_info: call delivers no result, return 0\n");
-               *eof = 1;
-               return 0;
-       }
-
-       if (buffer_length < (videocodec_bufsize - offset)) {
-               dprintk(4, "videocodec_info: %ld needed, %d got\n",
-                       videocodec_bufsize - offset, buffer_length);
-               size = buffer_length;
-       } else {
-               dprintk(4, "videocodec_info: last reading of %ld bytes\n",
-                       videocodec_bufsize - offset);
-               size = videocodec_bufsize - offset;
-               *eof = 1;
-       }
-
-       memcpy(buffer, videocodec_buf + offset, size);
-       /* doesn't work...                           */
-       /* copy_to_user(buffer, videocodec_buf+offset, size); */
-       /* *buffer_location = videocodec_buf+offset; */
-
-       return size;
+       return single_open(file, proc_videocodecs_show, NULL);
 }
+
+static const struct file_operations videocodecs_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_videocodecs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif
 
 /* ===================== */
@@ -444,16 +378,8 @@ videocodec_init (void)
               VIDEOCODEC_VERSION);
 
 #ifdef CONFIG_PROC_FS
-       videocodec_buf = NULL;
-       videocodec_bufsize = 0;
-
-       videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL);
-       if (videocodec_proc_entry) {
-               videocodec_proc_entry->read_proc = videocodec_info;
-               videocodec_proc_entry->write_proc = NULL;
-               videocodec_proc_entry->data = NULL;
-               videocodec_proc_entry->owner = THIS_MODULE;
-       } else {
+       videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
+       if (!videocodec_proc_entry) {
                dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
        }
 #endif
@@ -465,7 +391,6 @@ videocodec_exit (void)
 {
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("videocodecs", NULL);
-       kfree(videocodec_buf);
 #endif
 }
 
index 0d9b63762a48fd42aaaad60054d2a961dd1e83af..31e8af0ba2785e105e60587b8153602b948f55eb 100644 (file)
 
 #define dbgarg(cmd, fmt, arg...) \
                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {                \
-                       printk (KERN_DEBUG "%s: ",  vfd->name);         \
+                       printk(KERN_DEBUG "%s: ",  vfd->name);          \
                        v4l_printk_ioctl(cmd);                          \
-                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
+                       printk(" " fmt,  ## arg);                       \
                }
 
 #define dbgarg2(fmt, arg...) \
                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)                  \
-                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+                       printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -378,38 +378,45 @@ static const char *v4l2_int_ioctls[] = {
    external ioctl messages as well as internal V4L ioctl */
 void v4l_printk_ioctl(unsigned int cmd)
 {
-       char *dir;
+       char *dir, *type;
 
-       switch (_IOC_DIR(cmd)) {
-       case _IOC_NONE:              dir = "--"; break;
-       case _IOC_READ:              dir = "r-"; break;
-       case _IOC_WRITE:             dir = "-w"; break;
-       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
-       default:                     dir = "*ERR*"; break;
-       }
        switch (_IOC_TYPE(cmd)) {
        case 'd':
-               printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
-                      v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
+               if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
+                       type = "v4l2_int";
+                       break;
+               }
+               printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
+               return;
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        case 'v':
-               printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L1_IOCTLS) ?
-                      v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
+               if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
+                       type = "v4l1";
+                       break;
+               }
+               printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
+               return;
 #endif
        case 'V':
-               printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
-                      (_IOC_NR(cmd) < V4L2_IOCTLS) ?
-                      v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
-               break;
-
+               if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
+                       type = "v4l2";
+                       break;
+               }
+               printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
+               return;
        default:
-               printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
-                      _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+               type = "unknown";
+       }
+
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:              dir = "--"; break;
+       case _IOC_READ:              dir = "r-"; break;
+       case _IOC_WRITE:             dir = "-w"; break;
+       case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+       default:                     dir = "*ERR*"; break;
        }
+       printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
+               type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
 }
 EXPORT_SYMBOL(v4l_printk_ioctl);
 
@@ -774,6 +781,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
                                !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
                v4l_print_ioctl(vfd->name, cmd);
+               printk("\n");
        }
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -1853,12 +1861,20 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                        dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
                break;
        }
+       default:
+       {
+               if (!vfd->vidioc_default)
+                       break;
+               ret = vfd->vidioc_default(file, fh, cmd, arg);
+               break;
+       }
        } /* switch */
 
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
                if (ret<0) {
-                       printk ("%s: err:\n", vfd->name);
+                       printk("%s: err: on ", vfd->name);
                        v4l_print_ioctl(vfd->name, cmd);
+                       printk("\n");
                }
        }
 
@@ -2019,7 +2035,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
                        break;
                default:
                        printk(KERN_ERR "%s called with unknown type: %d\n",
-                              __FUNCTION__, type);
+                              __func__, type);
                        return -1;
        }
 
@@ -2057,7 +2073,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
        ret = device_register(&vfd->class_dev);
        if (ret < 0) {
                printk(KERN_ERR "%s: device_register failed\n",
-                      __FUNCTION__);
+                      __func__);
                goto fail_minor;
        }
 
index 5bb75294b5aa8142ef1e94b2d321db8955def494..d545c98dd5e7e3eb1a85c12ff64adfa977ba9345 100644 (file)
@@ -333,7 +333,7 @@ struct vino_settings {
  *
  * Use non-zero value to enable conversion.
  */
-static int vino_pixel_conversion = 0;
+static int vino_pixel_conversion;
 
 module_param_named(pixelconv, vino_pixel_conversion, int, 0);
 
@@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file,
 
 /* Initialization and cleanup */
 
-// __initdata
-static int vino_init_stage = 0;
+/* __initdata */
+static int vino_init_stage;
 
 static const struct file_operations vino_fops = {
        .owner          = THIS_MODULE,
@@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = {
 
 static struct video_device v4l_device_template = {
        .name           = "NOT SET",
-       //.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
-       //      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
+       /*.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */
+       /*      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */
        .fops           = &vino_fops,
        .minor          = -1,
 };
index 1db067c028157609c895b0124e72143acd94c8b2..b1e9592acb907bb06ca59d82e8fa6cafcf5384fc 100644 (file)
@@ -146,8 +146,6 @@ struct vivi_buffer {
 
 struct vivi_dmaqueue {
        struct list_head       active;
-       struct list_head       queued;
-       struct timer_list      timeout;
 
        /* thread for generating video stream*/
        struct task_struct         *kthread;
@@ -162,8 +160,8 @@ static LIST_HEAD(vivi_devlist);
 struct vivi_dev {
        struct list_head           vivi_devlist;
 
-       struct mutex               lock;
        spinlock_t                 slock;
+       struct mutex               mutex;
 
        int                        users;
 
@@ -322,24 +320,26 @@ static void gen_line(char *basep, int inipos, int wmax,
 end:
        return;
 }
+
 static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
 {
        int h , pos = 0;
        int hmax  = buf->vb.height;
        int wmax  = buf->vb.width;
        struct timeval ts;
-       char *tmpbuf = kmalloc(wmax * 2, GFP_KERNEL);
+       char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
        void *vbuf = videobuf_to_vmalloc(&buf->vb);
 
        if (!tmpbuf)
                return;
 
+       if (!vbuf)
+               return;
+
        for (h = 0; h < hmax; h++) {
                gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
                         dev->timestr);
-               /* FIXME: replacing to __copy_to_user */
-               if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0)
-                       dprintk(dev, 2, "vivifill copy_to_user failed.\n");
+               memcpy(vbuf + pos, tmpbuf, wmax * 2);
                pos += wmax*2;
        }
 
@@ -372,107 +372,71 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
                        dev->timestr, (unsigned long)tmpbuf, pos);
 
        /* Advice that buffer was filled */
-       buf->vb.state = VIDEOBUF_DONE;
        buf->vb.field_count++;
        do_gettimeofday(&ts);
        buf->vb.ts = ts;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
+       buf->vb.state = VIDEOBUF_DONE;
 }
 
-static int restart_video_queue(struct vivi_dmaqueue *dma_q);
-
-static void vivi_thread_tick(struct vivi_dmaqueue  *dma_q)
+static void vivi_thread_tick(struct vivi_fh *fh)
 {
-       struct vivi_buffer    *buf;
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_buffer *buf;
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
 
-       int bc;
+       unsigned long flags = 0;
 
-       spin_lock(&dev->slock);
-       /* Announces videobuf that all went ok */
-       for (bc = 0;; bc++) {
-               if (list_empty(&dma_q->active)) {
-                       dprintk(dev, 1, "No active queue to serve\n");
-                       break;
-               }
+       dprintk(dev, 1, "Thread tick\n");
 
-               buf = list_entry(dma_q->active.next,
-                                struct vivi_buffer, vb.queue);
+       spin_lock_irqsave(&dev->slock, flags);
+       if (list_empty(&dma_q->active)) {
+               dprintk(dev, 1, "No active queue to serve\n");
+               goto unlock;
+       }
 
-               /* Nobody is waiting something to be done, just return */
-               if (!waitqueue_active(&buf->vb.done)) {
-                       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-                       spin_unlock(&dev->slock);
-                       return;
-               }
+       buf = list_entry(dma_q->active.next,
+                        struct vivi_buffer, vb.queue);
+
+       /* Nobody is waiting on this buffer, return */
+       if (!waitqueue_active(&buf->vb.done))
+               goto unlock;
 
-               do_gettimeofday(&buf->vb.ts);
-               dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
+       list_del(&buf->vb.queue);
 
-               /* Fill buffer */
-               vivi_fillbuff(dev, buf);
+       do_gettimeofday(&buf->vb.ts);
 
-               if (list_empty(&dma_q->active)) {
-                       del_timer(&dma_q->timeout);
-               } else {
-                       mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
-               }
-       }
-       if (bc != 1)
-               dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n",
-                       __FUNCTION__, bc);
-       spin_unlock(&dev->slock);
+       /* Fill buffer */
+       vivi_fillbuff(dev, buf);
+       dprintk(dev, 1, "filled buffer %p\n", buf);
+
+       wake_up(&buf->vb.done);
+       dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
+unlock:
+       spin_unlock_irqrestore(&dev->slock, flags);
+       return;
 }
 
 #define frames_to_ms(frames)                                   \
        ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
 
-static void vivi_sleep(struct vivi_dmaqueue  *dma_q)
+static void vivi_sleep(struct vivi_fh *fh)
 {
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
-       int timeout, running_time;
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
+       int timeout;
        DECLARE_WAITQUEUE(wait, current);
 
-       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
+       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
                (unsigned long)dma_q);
 
        add_wait_queue(&dma_q->wq, &wait);
        if (kthread_should_stop())
                goto stop_task;
 
-       running_time = jiffies - dma_q->ini_jiffies;
-       dma_q->frame++;
-
        /* Calculate time to wake up */
-       timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time;
-
-       if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) {
-               int old = dma_q->frame;
-               int nframes;
-
-               dma_q->frame = (jiffies_to_msecs(running_time) /
-                              frames_to_ms(1)) + 1;
-
-               timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame))
-                         - running_time;
-
-               if (unlikely (timeout <= 0))
-                       timeout = 1;
-
-               nframes = (dma_q->frame > old)?
-                                 dma_q->frame - old : old - dma_q->frame;
-
-               dprintk(dev, 1, "%ld: %s %d frames. "
-                       "Current frame is %d. Will sleep for %d jiffies\n",
-                       jiffies,
-                       (dma_q->frame > old)? "Underrun, losed" : "Overrun of",
-                       nframes, dma_q->frame, timeout);
-       } else
-               dprintk(dev, 1, "will sleep for %d jiffies\n", timeout);
+       timeout = msecs_to_jiffies(frames_to_ms(1));
 
-       vivi_thread_tick(dma_q);
+       vivi_thread_tick(fh);
 
        schedule_timeout_interruptible(timeout);
 
@@ -483,16 +447,15 @@ stop_task:
 
 static int vivi_thread(void *data)
 {
-       struct vivi_dmaqueue  *dma_q = data;
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_fh  *fh = data;
+       struct vivi_dev *dev = fh->dev;
 
        dprintk(dev, 1, "thread started\n");
 
-       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
        set_freezable();
 
        for (;;) {
-               vivi_sleep(dma_q);
+               vivi_sleep(fh);
 
                if (kthread_should_stop())
                        break;
@@ -501,16 +464,17 @@ static int vivi_thread(void *data)
        return 0;
 }
 
-static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
+static int vivi_start_thread(struct vivi_fh *fh)
 {
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+       struct vivi_dev *dev = fh->dev;
+       struct vivi_dmaqueue *dma_q = &dev->vidq;
 
        dma_q->frame = 0;
        dma_q->ini_jiffies = jiffies;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
 
-       dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
+       dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
 
        if (IS_ERR(dma_q->kthread)) {
                printk(KERN_ERR "vivi: kernel_thread() failed\n");
@@ -519,7 +483,7 @@ static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
        /* Wakes thread */
        wake_up_interruptible(&dma_q->wq);
 
-       dprintk(dev, 1, "returning from %s\n", __FUNCTION__);
+       dprintk(dev, 1, "returning from %s\n", __func__);
        return 0;
 }
 
@@ -527,7 +491,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
 {
        struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
        /* shutdown control thread */
        if (dma_q->kthread) {
                kthread_stop(dma_q->kthread);
@@ -535,91 +499,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
        }
 }
 
-static int restart_video_queue(struct vivi_dmaqueue *dma_q)
-{
-       struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
-       struct vivi_buffer *buf, *prev;
-
-       dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
-               (unsigned long)dma_q);
-
-       if (!list_empty(&dma_q->active)) {
-               buf = list_entry(dma_q->active.next,
-                                struct vivi_buffer, vb.queue);
-               dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n",
-                       buf, buf->vb.i);
-
-               dprintk(dev, 1, "Restarting video dma\n");
-               vivi_stop_thread(dma_q);
-
-               /* cancel all outstanding capture / vbi requests */
-               list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) {
-                       list_del(&buf->vb.queue);
-                       buf->vb.state = VIDEOBUF_ERROR;
-                       wake_up(&buf->vb.done);
-               }
-               mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&dma_q->queued))
-                       return 0;
-               buf = list_entry(dma_q->queued.next,
-                                struct vivi_buffer, vb.queue);
-               if (NULL == prev) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &dma_q->active);
-
-                       dprintk(dev, 1, "Restarting video dma\n");
-                       vivi_stop_thread(dma_q);
-                       vivi_start_thread(dma_q);
-
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-                       dprintk(dev, 2,
-                               "[%p/%d] restart_queue - first active\n",
-                               buf, buf->vb.i);
-
-               } else if (prev->vb.width  == buf->vb.width  &&
-                          prev->vb.height == buf->vb.height &&
-                          prev->fmt       == buf->fmt) {
-                       list_del(&buf->vb.queue);
-                       list_add_tail(&buf->vb.queue, &dma_q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(dev, 2,
-                               "[%p/%d] restart_queue - move to active\n",
-                               buf, buf->vb.i);
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-static void vivi_vid_timeout(unsigned long data)
-{
-       struct vivi_dev      *dev  = (struct vivi_dev *)data;
-       struct vivi_dmaqueue *vidq = &dev->vidq;
-       struct vivi_buffer   *buf;
-
-       spin_lock(&dev->slock);
-
-       while (!list_empty(&vidq->active)) {
-               buf = list_entry(vidq->active.next,
-                                struct vivi_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
-       }
-       restart_video_queue(vidq);
-
-       spin_unlock(&dev->slock);
-}
-
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
@@ -637,7 +516,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
        while (*size * *count > vid_limit * 1024 * 1024)
                (*count)--;
 
-       dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__,
+       dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
                *count, *size);
 
        return 0;
@@ -648,13 +527,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
        struct vivi_fh  *fh = vq->priv_data;
        struct vivi_dev *dev  = fh->dev;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
 
        if (in_interrupt())
                BUG();
 
-       videobuf_waiton(&buf->vb, 0, 0);
        videobuf_vmalloc_free(&buf->vb);
+       dprintk(dev, 1, "free_buffer: freed\n");
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -667,28 +546,25 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
        struct vivi_fh     *fh  = vq->priv_data;
        struct vivi_dev    *dev = fh->dev;
        struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
-       int rc, init_buffer = 0;
+       int rc;
 
-       dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field);
+       dprintk(dev, 1, "%s, field=%d\n", __func__, field);
 
        BUG_ON(NULL == fh->fmt);
+
        if (fh->width  < 48 || fh->width  > norm_maxw() ||
            fh->height < 32 || fh->height > norm_maxh())
                return -EINVAL;
+
        buf->vb.size = fh->width*fh->height*2;
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
 
-       if (buf->fmt       != fh->fmt    ||
-           buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-       buf->vb.field  != field) {
-               buf->fmt       = fh->fmt;
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-               init_buffer = 1;
-       }
+       /* These properties only change when queue is idle, see s_fmt */
+       buf->fmt       = fh->fmt;
+       buf->vb.width  = fh->width;
+       buf->vb.height = fh->height;
+       buf->vb.field  = field;
 
        if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
                rc = videobuf_iolock(vq, &buf->vb, NULL);
@@ -711,45 +587,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        struct vivi_buffer    *buf  = container_of(vb, struct vivi_buffer, vb);
        struct vivi_fh        *fh   = vq->priv_data;
        struct vivi_dev       *dev  = fh->dev;
-       struct vivi_dmaqueue  *vidq = &dev->vidq;
-       struct vivi_buffer    *prev;
-
-       if (!list_empty(&vidq->queued)) {
-               dprintk(dev, 1, "adding vb queue=0x%08lx\n",
-                       (unsigned long)&buf->vb.queue);
-               list_add_tail(&buf->vb.queue, &vidq->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n",
-                       buf, buf->vb.i);
-       } else if (list_empty(&vidq->active)) {
-               list_add_tail(&buf->vb.queue, &vidq->active);
-
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n",
-                       buf, buf->vb.i);
-
-               vivi_start_thread(vidq);
-       } else {
-               prev = list_entry(vidq->active.prev,
-                                 struct vivi_buffer, vb.queue);
-               if (prev->vb.width  == buf->vb.width  &&
-                   prev->vb.height == buf->vb.height &&
-                   prev->fmt       == buf->fmt) {
-                       list_add_tail(&buf->vb.queue, &vidq->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(dev, 2,
-                               "[%p/%d] buffer_queue - append to active\n",
-                               buf, buf->vb.i);
-
-               } else {
-                       list_add_tail(&buf->vb.queue, &vidq->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(dev, 2,
-                               "[%p/%d] buffer_queue - first queued\n",
-                               buf, buf->vb.i);
-               }
-       }
+       struct vivi_dmaqueue *vidq = &dev->vidq;
+
+       dprintk(dev, 1, "%s\n", __func__);
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
 }
 
 static void buffer_release(struct videobuf_queue *vq,
@@ -758,11 +601,8 @@ static void buffer_release(struct videobuf_queue *vq,
        struct vivi_buffer   *buf  = container_of(vb, struct vivi_buffer, vb);
        struct vivi_fh       *fh   = vq->priv_data;
        struct vivi_dev      *dev  = (struct vivi_dev *)fh->dev;
-       struct vivi_dmaqueue *vidq = &dev->vidq;
-
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
 
-       vivi_stop_thread(vidq);
+       dprintk(dev, 1, "%s\n", __func__);
 
        free_buffer(vq, buf);
 }
@@ -869,17 +709,31 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct vivi_fh  *fh = priv;
+       struct videobuf_queue *q = &fh->vb_vidq;
+
        int ret = vidioc_try_fmt_cap(file, fh, f);
        if (ret < 0)
                return (ret);
 
+       mutex_lock(&q->vb_lock);
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               dprintk(fh->dev, 1, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+
        fh->fmt           = &format;
        fh->width         = f->fmt.pix.width;
        fh->height        = f->fmt.pix.height;
        fh->vb_vidq.field = f->fmt.pix.field;
        fh->type          = f->type;
 
-       return (0);
+       ret = 0;
+out:
+       mutex_unlock(&q->vb_lock);
+
+       return (ret);
 }
 
 static int vidioc_reqbufs(struct file *file, void *priv,
@@ -1036,6 +890,7 @@ static int vivi_open(struct inode *inode, struct file *file)
        struct vivi_dev *dev;
        struct vivi_fh *fh;
        int i;
+       int retval = 0;
 
        printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
 
@@ -1045,9 +900,15 @@ static int vivi_open(struct inode *inode, struct file *file)
        return -ENODEV;
 
 found:
-       /* If more than one user, mutex should be added */
+       mutex_lock(&dev->mutex);
        dev->users++;
 
+       if (dev->users > 1) {
+               dev->users--;
+               retval = -EBUSY;
+               goto unlock;
+       }
+
        dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
                v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
@@ -1055,8 +916,13 @@ found:
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
        if (NULL == fh) {
                dev->users--;
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto unlock;
        }
+unlock:
+       mutex_unlock(&dev->mutex);
+       if (retval)
+               return retval;
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -1084,6 +950,8 @@ found:
                        NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
                        sizeof(struct vivi_buffer), fh);
 
+       vivi_start_thread(fh);
+
        return 0;
 }
 
@@ -1106,7 +974,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
        struct vivi_dev       *dev = fh->dev;
        struct videobuf_queue *q = &fh->vb_vidq;
 
-       dprintk(dev, 1, "%s\n", __FUNCTION__);
+       dprintk(dev, 1, "%s\n", __func__);
 
        if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
                return POLLERR;
@@ -1128,7 +996,9 @@ static int vivi_close(struct inode *inode, struct file *file)
 
        kfree(fh);
 
+       mutex_lock(&dev->mutex);
        dev->users--;
+       mutex_unlock(&dev->mutex);
 
        dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
                minor, dev->users);
@@ -1182,6 +1052,7 @@ static const struct file_operations vivi_fops = {
        .read           = vivi_read,
        .poll           = vivi_poll,
        .ioctl          = video_ioctl2, /* V4L2 ioctl handler */
+       .compat_ioctl   = v4l_compat_ioctl32,
        .mmap           = vivi_mmap,
        .llseek         = no_llseek,
 };
@@ -1236,16 +1107,11 @@ static int __init vivi_init(void)
 
                /* init video dma queues */
                INIT_LIST_HEAD(&dev->vidq.active);
-               INIT_LIST_HEAD(&dev->vidq.queued);
                init_waitqueue_head(&dev->vidq.wq);
 
                /* initialize locks */
-               mutex_init(&dev->lock);
                spin_lock_init(&dev->slock);
-
-               dev->vidq.timeout.function = vivi_vid_timeout;
-               dev->vidq.timeout.data     = (unsigned long)dev;
-               init_timer(&dev->vidq.timeout);
+               mutex_init(&dev->mutex);
 
                vfd = video_device_alloc();
                if (NULL == vfd)
index a9133858e913552e62474792ad6b647a0865edd5..35293029da02423e1c31cb1aedb136f78c6b090f 100644 (file)
@@ -40,7 +40,7 @@
 #define I2C_VPX3220        0x86
 #define VPX3220_DEBUG  KERN_DEBUG "vpx3220: "
 
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
index 08aaae07c7e0cb3c4a58e386bb49312068c2f613..33f702698a56f06d629bceb96bef454661282855 100644 (file)
 #include <media/v4l2-common.h>
 #include <linux/parport.h>
 
-//#define DEBUG                                // Undef me for production
+/*#define DEBUG*/                              /* Undef me for production */
 
 #ifdef DEBUG
-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a)
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
 #else
 #define DPRINTF(x...)
 #endif
@@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
 \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\
 \tcam 1 to parport3 and search every parport for cam 2 etc...");
 
-static int parmode = 0;
+static int parmode;
 module_param(parmode, int, 0);
 MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
 
@@ -188,7 +188,9 @@ static const struct file_operations w9966_fops = {
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = w9966_v4l_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .read           = w9966_v4l_read,
        .llseek         = no_llseek,
 };
index 2ae1430f5f7d0165942d2427d80fdaa833448213..840522442d07d4a6316a76a7f658481da60de77f 100644 (file)
@@ -3461,7 +3461,9 @@ static const struct file_operations w9968cf_fops = {
        .release = w9968cf_release,
        .read =    w9968cf_read,
        .ioctl =   w9968cf_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .mmap =    w9968cf_mmap,
        .llseek =  no_llseek,
 };
@@ -3481,7 +3483,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        enum w9968cf_model_id mod_id;
        struct list_head* ptr;
        u8 sc = 0; /* number of simultaneous cameras */
-       static unsigned short dev_nr = 0; /* we are handling device number n */
+       static unsigned short dev_nr; /* 0 - we are handling device number n */
 
        if (le16_to_cpu(udev->descriptor.idVendor)  == winbond_id_table[0].idVendor &&
            le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
index ec7696e8f1fac3eaf3b47725c37db3ec1dde8154..3c95316bc030cf7dcbcfea1023a4cc5b5426eec7 100644 (file)
@@ -298,7 +298,7 @@ struct w9968cf_device {
                        dev_warn(&cam->dev, fmt "\n", ## args);               \
                else if ((level) >= 5)                                        \
                        dev_info(&cam->dev, "[%s:%d] " fmt "\n",              \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 }
 /* For generic kernel (not device specific) messages */
@@ -309,7 +309,7 @@ struct w9968cf_device {
                if ((level) >= 1 && (level) <= 4)                             \
                        pr_info("w9968cf: " fmt "\n", ## args);               \
                else if ((level) >= 5)                                        \
-                       pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__,  \
+                       pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__,  \
                                 __LINE__ , ## args);                         \
        }                                                                     \
 }
@@ -321,7 +321,7 @@ struct w9968cf_device {
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
 
 #undef PDBGG
 #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
index a2de50efa31adec2c439b182070e8db95f6e7781..7bbab541a309d59f6141b7a0b10ff918baf945ce 100644 (file)
@@ -160,7 +160,7 @@ do {                                                                          \
                        dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
                else if ((level) >= 3)                                        \
                        dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-                                __FILE__, __FUNCTION__, __LINE__ , ## args); \
+                                __FILE__, __func__, __LINE__ , ## args); \
        }                                                                     \
 } while (0)
 #      define KDBG(level, fmt, args...)                                      \
@@ -170,7 +170,7 @@ do {                                                                          \
                        pr_info("zc0301: " fmt "\n", ## args);                \
                else if ((level) == 3)                                        \
                        pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-                                __FUNCTION__, __LINE__ , ## args);           \
+                                __func__, __LINE__ , ## args);           \
        }                                                                     \
 } while (0)
 #      define V4LDBG(level, name, cmd)                                       \
@@ -186,7 +186,7 @@ do {                                                                          \
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
         __LINE__ , ## args)
 
 #undef PDBGG
index 2c5665c824423360481ea49a5f388a4a79c76223..363dd2b9475cfe40ca30fd3adfecdb2689d59d8c 100644 (file)
@@ -1925,7 +1925,9 @@ static const struct file_operations zc0301_fops = {
        .open =    zc0301_open,
        .release = zc0301_release,
        .ioctl =   zc0301_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .read =    zc0301_read,
        .poll =    zc0301_poll,
        .mmap =    zc0301_mmap,
@@ -1939,7 +1941,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct zc0301_device* cam;
-       static unsigned int dev_nr = 0;
+       static unsigned int dev_nr;
        unsigned int i;
        int err = 0;
 
index 498a43c1f2b1595fc2352c56a5fad686d971a4a0..81cc3b00a07912bbf0d512055151c0bfbce6c509 100644 (file)
@@ -243,10 +243,8 @@ struct zoran_format {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        int palette;
 #endif
-#ifdef CONFIG_VIDEO_V4L2
        __u32 fourcc;
        int colorspace;
-#endif
        int depth;
        __u32 flags;
        __u32 vfespfr;
@@ -271,20 +269,6 @@ struct zoran_v4l_settings {
        const struct zoran_format *format;      /* capture format */
 };
 
-/* whoops, this one is undeclared if !v4l2 */
-#ifndef CONFIG_VIDEO_V4L2
-struct v4l2_jpegcompression {
-       int quality;
-       int APPn;
-       int APP_len;
-       char APP_data[60];
-       int COM_len;
-       char COM_data[60];
-       __u32 jpeg_markers;
-       __u8 reserved[116];
-};
-#endif
-
 /* jpg-capture/-playback settings */
 struct zoran_jpg_settings {
        int decimation;         /* this bit is used to set everything to default */
index 690281bb59ee616f71db4393d7b63a4080455284..006d48847e24a90396c0cfdaf29ad83554746a34 100644 (file)
@@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder");
    or set in in a VIDIOCSFBUF ioctl
  */
 
-static unsigned long vidmem = 0;       /* Video memory base address */
+static unsigned long vidmem;   /* default = 0 - Video memory base address */
 module_param(vidmem, ulong, 0444);
 MODULE_PARM_DESC(vidmem, "Default video memory base address");
 
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address");
    Default input and video norm at startup of the driver.
 */
 
-static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */
+static unsigned int default_input;     /* default 0 = Composite, 1 = S-Video */
 module_param(default_input, uint, 0444);
 MODULE_PARM_DESC(default_input,
                 "Default input (0=Composite, 1=S-Video, 2=Internal)");
@@ -101,7 +101,7 @@ module_param(default_mux, int, 0644);
 MODULE_PARM_DESC(default_mux,
                 "Default 6 Eyes mux setting (Input selection)");
 
-static int default_norm = 0;   /* 0=PAL, 1=NTSC 2=SECAM */
+static int default_norm;       /* default 0 = PAL, 1 = NTSC 2 = SECAM */
 module_param(default_norm, int, 0444);
 MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
 
index 8444ca0a5f3fd72837554f3edada9dbcbc4918dc..1b5c4171cf9c37f0b7c3f6f365490ded31b95da2 100644 (file)
@@ -50,4 +50,6 @@ extern int zoran_check_jpg_settings(struct zoran *zr,
 extern void zoran_open_init_params(struct zoran *zr);
 extern void zoran_vdev_release(struct video_device *vdev);
 
+void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
+
 #endif                         /* __ZORAN_CARD_H__ */
index f97c206920579997c5e003c70ab9afb84998a9e9..7b60533efe456bb4b650f060acc02bf66396f1de 100644 (file)
@@ -60,7 +60,8 @@
 
 extern const struct zoran_format zoran_formats[];
 
-static int lml33dpath = 0;     /* 1 will use digital path in capture
+static int lml33dpath;         /* default = 0
+                                * 1 will use digital path in capture
                                 * mode instead of analog. It can be
                                 * used for picture adjustments using
                                 * tool like xawtv while watching image
@@ -927,11 +928,6 @@ count_reset_interrupt (struct zoran *zr)
        return isr;
 }
 
-/* hack */
-extern void zr36016_write (struct videocodec *codec,
-                          u16                reg,
-                          u32                val);
-
 void
 jpeg_start (struct zoran *zr)
 {
@@ -987,7 +983,7 @@ void
 zr36057_enable_jpg (struct zoran          *zr,
                    enum zoran_codec_mode  mode)
 {
-       static int zero = 0;
+       static int zero;
        static int one = 1;
        struct vfe_settings cap;
        int field_size =
@@ -1726,7 +1722,7 @@ decoder_command (struct zoran *zr,
                return -EIO;
 
        if (zr->card.type == LML33 &&
-           (cmd == DECODER_SET_NORM || DECODER_SET_INPUT)) {
+           (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
                int res;
 
                // Bt819 needs to reset its FIFO buffer using #FRST pin and
index fea4946ee713c82d4b17eaff5864ccb943a9f545..0134bec1e399e66fca43153dbe64c6c9066d84c0 100644 (file)
@@ -85,7 +85,6 @@
 #include "zoran_device.h"
 #include "zoran_card.h"
 
-#ifdef CONFIG_VIDEO_V4L2
        /* we declare some card type definitions here, they mean
         * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
 #define ZORAN_V4L2_VID_FLAGS ( \
                                V4L2_CAP_VIDEO_OUTPUT |\
                                V4L2_CAP_VIDEO_OVERLAY \
                              )
-#endif
 
 #include <asm/byteorder.h>
 
-#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
+#if defined(CONFIG_VIDEO_V4L1_COMPAT)
 #define ZFMT(pal, fcc, cs) \
        .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
-#elif defined(CONFIG_VIDEO_V4L2)
-#define ZFMT(pal, fcc, cs) \
-       .fourcc = (fcc), .colorspace = (cs)
 #else
 #define ZFMT(pal, fcc, cs) \
-       .palette = (pal)
+       .fourcc = (fcc), .colorspace = (cs)
 #endif
 
 const struct zoran_format zoran_formats[] = {
@@ -205,11 +200,10 @@ extern int jpg_nbufs;
 extern int jpg_bufsize;
 extern int pass_through;
 
-static int lock_norm = 0;      /* 1=Don't change TV standard (norm) */
+static int lock_norm;  /* 0 = default 1 = Don't change TV standard (norm) */
 module_param(lock_norm, int, 0644);
 MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
 
-#ifdef CONFIG_VIDEO_V4L2
        /* small helper function for calculating buffersizes for v4l2
         * we calculate the nearest higher power-of-two, which
         * will be the recommended buffersize */
@@ -232,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
                return 8192;
        return result;
 }
-#endif
 
 /* forward references */
 static void v4l_fbuffer_free(struct file *file);
@@ -1709,7 +1702,6 @@ setup_overlay (struct file *file,
        return wait_grab_pending(zr);
 }
 
-#ifdef CONFIG_VIDEO_V4L2
        /* get the status of a buffer in the clients buffer queue */
 static int
 zoran_v4l2_buffer_status (struct file        *file,
@@ -1815,7 +1807,6 @@ zoran_v4l2_buffer_status (struct file        *file,
 
        return 0;
 }
-#endif
 
 static int
 zoran_set_norm (struct zoran *zr,
@@ -2624,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode,
        }
                break;
 
-#ifdef CONFIG_VIDEO_V4L2
-
                /* The new video4linux2 capture interface - much nicer than video4linux1, since
                 * it allows for integrating the JPEG capturing calls inside standard v4l2
                 */
@@ -4197,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode,
                return 0;
        }
                break;
-#endif
 
        default:
                dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
@@ -4247,7 +4235,7 @@ zoran_poll (struct file *file,
                dprintk(3,
                        KERN_DEBUG
                        "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
-                       ZR_DEVNAME(zr), __FUNCTION__,
+                       ZR_DEVNAME(zr), __func__,
                        "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
                        "UPMD"[zr->v4l_buffers.buffer[frame].state],
                        zr->v4l_pend_tail, zr->v4l_pend_head);
@@ -4269,7 +4257,7 @@ zoran_poll (struct file *file,
                dprintk(3,
                        KERN_DEBUG
                        "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
-                       ZR_DEVNAME(zr), __FUNCTION__,
+                       ZR_DEVNAME(zr), __func__,
                        "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
                        "UPMD"[zr->jpg_buffers.buffer[frame].state],
                        zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
@@ -4644,7 +4632,9 @@ static const struct file_operations zoran_fops = {
        .open = zoran_open,
        .release = zoran_close,
        .ioctl = zoran_ioctl,
+#ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek,
        .read = zoran_read,
        .write = zoran_write,
@@ -4655,9 +4645,7 @@ static const struct file_operations zoran_fops = {
 struct video_device zoran_template __devinitdata = {
        .name = ZORAN_NAME,
        .type = ZORAN_VID_TYPE,
-#ifdef CONFIG_VIDEO_V4L2
        .type2 = ZORAN_V4L2_VID_FLAGS,
-#endif
        .fops = &zoran_fops,
        .release = &zoran_vdev_release,
        .minor = -1
index dd084555da8f8f19c20cfb59455b62b0aefb4579..00d132bcd1e4fecb64860d9d165a61eedc547b29 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36016_codecs = 0;
+static int zr36016_codecs;
 
 /* debugging is available via module parameter */
-
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index faae4ec3ea0bf5288f12a1c52a78ce75e12bd7c2..cf8b271a1c8f1907e3885773ba5dad02d67f07cf 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36050_codecs = 0;
+static int zr36050_codecs;
 
 /* debugging is available via module parameter */
-
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index 7849b65969d0741e624b350aa80e79eb18d50321..8e74054d5ef10ea0615fbf927f3e17b06c04a81e 100644 (file)
 #define MAX_CODECS 20
 
 /* amount of chips attached via this driver */
-static int zr36060_codecs = 0;
+static int zr36060_codecs;
 
-static int low_bitrate = 0;
+static int low_bitrate;
 module_param(low_bitrate, bool, 0);
 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
 
 /* debugging is available via module parameter */
-static int debug = 0;
+static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
index 04949c823654db4b4e95d4a4814d73a23a029d02..a0e49dc66301f06af6130441c9cc1e0fac6b50b2 100644 (file)
@@ -62,8 +62,8 @@
 
 
 /* Module parameters */
-static int debug = 0;
-static int mode = 0;
+static int debug;
+static int mode;
 
 
 /* Module parameters interface */
index c6a2353c4e68f2831db0007fcc9d9070da1202ae..402fb7a8d922531809a2b19a4ec1d590587e578f 100644 (file)
@@ -39,9 +39,10 @@ typedef enum
        DMX_OUT_DECODER, /* Streaming directly to decoder. */
        DMX_OUT_TAP,     /* Output going to a memory buffer */
                         /* (to be retrieved via the read command).*/
-       DMX_OUT_TS_TAP   /* Output multiplexed into a new TS  */
+       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
                         /* (to be retrieved by reading from the */
                         /* logical DVR device).                 */
+       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
 } dmx_output_t;
 
 
index b979112f74e0d3aca3242d5ca8f8fda9c96067ac..32eb8bbe48317d4acacfcb9719f4ea44f2287d9f 100644 (file)
 #define I2C_HW_B_CX2341X       0x010020 /* Conexant CX2341X MPEG encoder cards */
 #define I2C_HW_B_INTELFB       0x010021 /* intel framebuffer driver */
 #define I2C_HW_B_CX23885       0x010022 /* conexant 23885 based tv cards (bus1) */
+#define I2C_HW_B_AU0828                0x010023 /* auvitek au0828 usb bridge */
 
 /* --- PCF 8584 based algorithms                                       */
 #define I2C_HW_P_ELEK          0x020002 /* Elektor ISA Bus inteface card */
index 39fd9c8ddd4b27b2adcf14659e5b4477a3ba8194..12010ace1f04abd1d556cdb3b9e4935a0d697af7 100644 (file)
@@ -58,7 +58,7 @@ struct meye_params {
 
 /* V4L2 private controls */
 #define V4L2_CID_AGC           V4L2_CID_PRIVATE_BASE
-#define V4L2_CID_SHARPNESS     (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_MEYE_SHARPNESS        (V4L2_CID_PRIVATE_BASE + 1)
 #define V4L2_CID_PICTURE       (V4L2_CID_PRIVATE_BASE + 2)
 #define V4L2_CID_JPEGQUAL      (V4L2_CID_PRIVATE_BASE + 3)
 #define V4L2_CID_FRAMERATE     (V4L2_CID_PRIVATE_BASE + 4)
index 17a80177a674194460f389a331f2fead05a80818..c1411189ba6c5983f3396a60f801f21ee2688789 100644 (file)
@@ -282,6 +282,7 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B','G','R','4') /* 32  BGR-8-8-8-8   */
 #define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R','G','B','4') /* 32  RGB-8-8-8-8   */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G','R','E','Y') /*  8  Greyscale     */
+#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y','1','6',' ') /* 16  Greyscale     */
 #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P','A','L','8') /*  8  8-bit palette */
 #define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y','V','U','9') /*  9  YVU 4:1:0     */
 #define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y','V','1','2') /* 12  YVU 4:2:0     */
@@ -308,6 +309,7 @@ struct v4l2_pix_format
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16  BGBG.. GRGR.. */
 
 /* compressed formats */
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
@@ -793,6 +795,7 @@ struct v4l2_ext_controls
 /*  Values for ctrl_class field */
 #define V4L2_CTRL_CLASS_USER 0x00980000        /* Old-style 'user' controls */
 #define V4L2_CTRL_CLASS_MPEG 0x00990000        /* MPEG-compression controls */
+#define V4L2_CTRL_CLASS_CAMERA 0x009a0000      /* Camera class controls */
 
 #define V4L2_CTRL_ID_MASK                (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
@@ -849,21 +852,37 @@ struct v4l2_querymenu
 #define V4L2_CID_AUDIO_TREBLE          (V4L2_CID_BASE+8)
 #define V4L2_CID_AUDIO_MUTE            (V4L2_CID_BASE+9)
 #define V4L2_CID_AUDIO_LOUDNESS                (V4L2_CID_BASE+10)
-#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11)
+#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11) /* Deprecated */
 #define V4L2_CID_AUTO_WHITE_BALANCE    (V4L2_CID_BASE+12)
 #define V4L2_CID_DO_WHITE_BALANCE      (V4L2_CID_BASE+13)
 #define V4L2_CID_RED_BALANCE           (V4L2_CID_BASE+14)
 #define V4L2_CID_BLUE_BALANCE          (V4L2_CID_BASE+15)
 #define V4L2_CID_GAMMA                 (V4L2_CID_BASE+16)
-#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* ? Not sure */
+#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* Deprecated */
 #define V4L2_CID_EXPOSURE              (V4L2_CID_BASE+17)
 #define V4L2_CID_AUTOGAIN              (V4L2_CID_BASE+18)
 #define V4L2_CID_GAIN                  (V4L2_CID_BASE+19)
 #define V4L2_CID_HFLIP                 (V4L2_CID_BASE+20)
 #define V4L2_CID_VFLIP                 (V4L2_CID_BASE+21)
-#define V4L2_CID_HCENTER               (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER               (V4L2_CID_BASE+23)
-#define V4L2_CID_LASTP1                        (V4L2_CID_BASE+24) /* last CID + 1 */
+
+/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
+#define V4L2_CID_HCENTER_DEPRECATED    (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER_DEPRECATED    (V4L2_CID_BASE+23)
+
+#define V4L2_CID_POWER_LINE_FREQUENCY  (V4L2_CID_BASE+24)
+enum v4l2_power_line_frequency {
+       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
+       V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
+       V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
+};
+#define V4L2_CID_HUE_AUTO                      (V4L2_CID_BASE+25)
+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE     (V4L2_CID_BASE+26)
+#define V4L2_CID_SHARPNESS                     (V4L2_CID_BASE+27)
+#define V4L2_CID_BACKLIGHT_COMPENSATION        (V4L2_CID_BASE+28)
+#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
+#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
+/* last CID + 1 */
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+31)
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1051,6 +1070,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type {
 #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
 #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS        (V4L2_CID_MPEG_CX2341X_BASE+11)
 
+/*  Camera class control IDs */
+#define V4L2_CID_CAMERA_CLASS_BASE     (V4L2_CTRL_CLASS_CAMERA | 0x900)
+#define V4L2_CID_CAMERA_CLASS          (V4L2_CTRL_CLASS_CAMERA | 1)
+
+#define V4L2_CID_EXPOSURE_AUTO                 (V4L2_CID_CAMERA_CLASS_BASE+1)
+enum  v4l2_exposure_auto_type {
+       V4L2_EXPOSURE_AUTO = 0,
+       V4L2_EXPOSURE_MANUAL = 1,
+       V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
+       V4L2_EXPOSURE_APERTURE_PRIORITY = 3
+};
+#define V4L2_CID_EXPOSURE_ABSOLUTE             (V4L2_CID_CAMERA_CLASS_BASE+2)
+#define V4L2_CID_EXPOSURE_AUTO_PRIORITY                (V4L2_CID_CAMERA_CLASS_BASE+3)
+
+#define V4L2_CID_PAN_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+4)
+#define V4L2_CID_TILT_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+5)
+#define V4L2_CID_PAN_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+6)
+#define V4L2_CID_TILT_RESET                    (V4L2_CID_CAMERA_CLASS_BASE+7)
+
+#define V4L2_CID_PAN_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+8)
+#define V4L2_CID_TILT_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+9)
+
+#define V4L2_CID_FOCUS_ABSOLUTE                        (V4L2_CID_CAMERA_CLASS_BASE+10)
+#define V4L2_CID_FOCUS_RELATIVE                        (V4L2_CID_CAMERA_CLASS_BASE+11)
+#define V4L2_CID_FOCUS_AUTO                    (V4L2_CID_CAMERA_CLASS_BASE+12)
+
 /*
  *     T U N I N G
  */
index a4274203f25298ca78aafece33c91bf8de40bfc5..bfee8be5d63fb6b69765535a8384e928017b8b40 100644 (file)
@@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE];
@@ -141,8 +142,10 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
 
 #endif
 
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
new file mode 100644 (file)
index 0000000..6a8c8be
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * camera image capture (abstract) bus driver header
+ *
+ * Copyright (C) 2006, Sascha Hauer, Pengutronix
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef SOC_CAMERA_H
+#define SOC_CAMERA_H
+
+#include <linux/videodev2.h>
+#include <media/videobuf-dma-sg.h>
+
+struct soc_camera_device {
+       struct list_head list;
+       struct device dev;
+       struct device *control;
+       unsigned short width;           /* Current window */
+       unsigned short height;          /* sizes */
+       unsigned short x_min;           /* Camera capabilities */
+       unsigned short y_min;
+       unsigned short x_current;       /* Current window location */
+       unsigned short y_current;
+       unsigned short width_min;
+       unsigned short width_max;
+       unsigned short height_min;
+       unsigned short height_max;
+       unsigned short y_skip_top;      /* Lines to skip at the top */
+       unsigned short gain;
+       unsigned short exposure;
+       unsigned char iface;            /* Host number */
+       unsigned char devnum;           /* Device number per host */
+       unsigned char buswidth;         /* See comment in .c */
+       struct soc_camera_ops *ops;
+       struct video_device *vdev;
+       const struct soc_camera_data_format *current_fmt;
+       const struct soc_camera_data_format *formats;
+       int num_formats;
+       struct module *owner;
+       /* soc_camera.c private count. Only accessed with video_lock held */
+       int use_count;
+};
+
+struct soc_camera_file {
+       struct soc_camera_device *icd;
+       struct videobuf_queue vb_vidq;
+       spinlock_t *lock;
+};
+
+struct soc_camera_host {
+       struct list_head list;
+       struct device dev;
+       unsigned char nr;                               /* Host number */
+       size_t msize;
+       struct videobuf_queue_ops *vbq_ops;
+       void *priv;
+       char *drv_name;
+       struct soc_camera_host_ops *ops;
+};
+
+struct soc_camera_host_ops {
+       struct module *owner;
+       int (*add)(struct soc_camera_device *);
+       void (*remove)(struct soc_camera_device *);
+       int (*set_fmt_cap)(struct soc_camera_device *, __u32,
+                          struct v4l2_rect *);
+       int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
+       int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
+       int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
+       int (*try_bus_param)(struct soc_camera_device *, __u32);
+       int (*set_bus_param)(struct soc_camera_device *, __u32);
+       unsigned int (*poll)(struct file *, poll_table *);
+       spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
+       void (*spinlock_free)(spinlock_t *);
+};
+
+struct soc_camera_link {
+       /* Camera bus id, used to match a camera and a bus */
+       int bus_id;
+       /* GPIO number to switch between 8 and 10 bit modes */
+       unsigned int gpio;
+};
+
+static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
+{
+       return container_of(dev, struct soc_camera_device, dev);
+}
+
+static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
+{
+       return container_of(dev, struct soc_camera_host, dev);
+}
+
+extern int soc_camera_host_register(struct soc_camera_host *ici);
+extern void soc_camera_host_unregister(struct soc_camera_host *ici);
+extern int soc_camera_device_register(struct soc_camera_device *icd);
+extern void soc_camera_device_unregister(struct soc_camera_device *icd);
+
+extern int soc_camera_video_start(struct soc_camera_device *icd);
+extern void soc_camera_video_stop(struct soc_camera_device *icd);
+
+struct soc_camera_data_format {
+       char *name;
+       unsigned int depth;
+       __u32 fourcc;
+       enum v4l2_colorspace colorspace;
+};
+
+struct soc_camera_ops {
+       struct module *owner;
+       int (*probe)(struct soc_camera_device *);
+       void (*remove)(struct soc_camera_device *);
+       int (*init)(struct soc_camera_device *);
+       int (*release)(struct soc_camera_device *);
+       int (*start_capture)(struct soc_camera_device *);
+       int (*stop_capture)(struct soc_camera_device *);
+       int (*set_fmt_cap)(struct soc_camera_device *, __u32,
+                          struct v4l2_rect *);
+       int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
+       unsigned long (*query_bus_param)(struct soc_camera_device *);
+       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
+       int (*get_chip_id)(struct soc_camera_device *,
+                          struct v4l2_chip_ident *);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       int (*get_register)(struct soc_camera_device *, struct v4l2_register *);
+       int (*set_register)(struct soc_camera_device *, struct v4l2_register *);
+#endif
+       int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
+       int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
+       const struct v4l2_queryctrl *controls;
+       int num_controls;
+};
+
+static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
+       struct soc_camera_ops *ops, int id)
+{
+       int i;
+
+       for (i = 0; i < ops->num_controls; i++)
+               if (ops->controls[i].id == id)
+                       return &ops->controls[i];
+
+       return NULL;
+}
+
+#define SOCAM_MASTER                   (1 << 0)
+#define SOCAM_SLAVE                    (1 << 1)
+#define SOCAM_HSYNC_ACTIVE_HIGH                (1 << 2)
+#define SOCAM_HSYNC_ACTIVE_LOW         (1 << 3)
+#define SOCAM_VSYNC_ACTIVE_HIGH                (1 << 4)
+#define SOCAM_VSYNC_ACTIVE_LOW         (1 << 5)
+#define SOCAM_DATAWIDTH_8              (1 << 6)
+#define SOCAM_DATAWIDTH_9              (1 << 7)
+#define SOCAM_DATAWIDTH_10             (1 << 8)
+#define SOCAM_PCLK_SAMPLE_RISING       (1 << 9)
+#define SOCAM_PCLK_SAMPLE_FALLING      (1 << 10)
+
+#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
+                             SOCAM_DATAWIDTH_10)
+
+static inline unsigned long soc_camera_bus_param_compatible(
+                       unsigned long camera_flags, unsigned long bus_flags)
+{
+       unsigned long common_flags, hsync, vsync, pclk;
+
+       common_flags = camera_flags & bus_flags;
+
+       hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
+       vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
+       pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
+
+       return (!hsync || !vsync || !pclk) ? 0 : common_flags;
+}
+
+#endif
index b201371416a0c793473b1fdd96dc9885f06746d5..ab03c5344209937818de9200a9f33b678e64c2c5 100644 (file)
@@ -6,10 +6,11 @@
 #define __TUNER_TYPES_H__
 
 enum param_type {
-       TUNER_PARAM_TYPE_RADIO, \
-       TUNER_PARAM_TYPE_PAL, \
-       TUNER_PARAM_TYPE_SECAM, \
-       TUNER_PARAM_TYPE_NTSC
+       TUNER_PARAM_TYPE_RADIO,
+       TUNER_PARAM_TYPE_PAL,
+       TUNER_PARAM_TYPE_SECAM,
+       TUNER_PARAM_TYPE_NTSC,
+       TUNER_PARAM_TYPE_DIGITAL,
 };
 
 struct tuner_range {
@@ -105,6 +106,7 @@ struct tuner_params {
           the SECAM-L/L' standards. Range: -16:+15 */
        signed int default_top_secam_high:5;
 
+       u16 iffreq;
 
        unsigned int count;
        struct tuner_range *ranges;
@@ -114,6 +116,13 @@ struct tunertype {
        char *name;
        unsigned int count;
        struct tuner_params *params;
+
+       u16 min;
+       u16 max;
+       u32 stepsize;
+
+       u8 *initdata;
+       u8 *sleepdata;
 };
 
 extern struct tunertype tuners[];
index 1bf24a6ed8f10e4fbc0bbb25ab04dda09a20fd83..77068fcc86bd9cb60a801732b24b67e28fc75103 100644 (file)
@@ -78,7 +78,7 @@
 
 #define TUNER_HITACHI_NTSC             40
 #define TUNER_PHILIPS_PAL_MK           41
-#define TUNER_PHILIPS_ATSC             42
+#define TUNER_PHILIPS_FCV1236D         42
 #define TUNER_PHILIPS_FM1236_MK3       43
 
 #define TUNER_PHILIPS_4IN1             44      /* ATI TV Wonder Pro - Conexant */
index 032bb75f69c2ea7b92be53f274a52799c20e43eb..0ea0bd85c0368543dae9bc754e7cd97dd50be61d 100644 (file)
@@ -153,6 +153,12 @@ enum {
        V4L2_IDENT_MSP4428G = 44287,
        V4L2_IDENT_MSP4448G = 44487,
        V4L2_IDENT_MSP4458G = 44587,
+
+       /* Micron CMOS sensor chips: 45000-45099 */
+       V4L2_IDENT_MT9M001C12ST         = 45000,
+       V4L2_IDENT_MT9M001C12STM        = 45005,
+       V4L2_IDENT_MT9V022IX7ATC        = 45010, /* No way to detect "normal" I77ATx */
+       V4L2_IDENT_MT9V022IX7ATM        = 45015, /* and "lead free" IA7ATx chips */
 };
 
 #endif
index f2114459995d94826b9530e3a4f9c6feea1e5b00..a807d2f86ee849a5201ebfffc3ea54ff5c66e32e 100644 (file)
@@ -318,6 +318,10 @@ struct video_device
        int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
                                        struct v4l2_chip_ident *chip);
 
+       /* For other private ioctls */
+       int (*vidioc_default)          (struct file *file, void *fh,
+                                       int cmd, void *arg);
+
 
 #ifdef OBSOLETE_OWNER /* to be removed soon */
 /* obsolete -- fops->owner is used instead */
index 99033945cdee3790c45240ac0f43a2f61fdec749..5b39a22533fea113254186a9157c9b24f0be5bbf 100644 (file)
@@ -13,6 +13,9 @@
  * the Free Software Foundation; either version 2
  */
 
+#ifndef _VIDEOBUF_CORE_H
+#define _VIDEOBUF_CORE_H
+
 #include <linux/poll.h>
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 #include <linux/videodev.h>
@@ -123,7 +126,8 @@ struct videobuf_queue_ops {
 struct videobuf_qtype_ops {
        u32                     magic;
 
-       void* (*alloc)          (size_t size);
+       void *(*alloc)          (size_t size);
+       void *(*vmalloc)        (struct videobuf_buffer *buf);
        int (*iolock)           (struct videobuf_queue* q,
                                 struct videobuf_buffer *vb,
                                 struct v4l2_framebuffer *fbuf);
@@ -151,7 +155,9 @@ struct videobuf_qtype_ops {
 struct videobuf_queue {
        struct mutex               vb_lock;
        spinlock_t                 *irqlock;
-       void                       *dev; /* on pci, points to struct pci_dev */
+       struct device              *dev;
+
+       wait_queue_head_t          wait; /* wait if queue is empty */
 
        enum v4l2_buf_type         type;
        unsigned int               inputs; /* for V4L2_BUF_FLAG_INPUT */
@@ -183,9 +189,13 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
 
 void *videobuf_alloc(struct videobuf_queue* q);
 
+/* Used on videobuf-dvb */
+void *videobuf_queue_to_vmalloc (struct videobuf_queue* q,
+                                struct videobuf_buffer *buf);
+
 void videobuf_queue_core_init(struct videobuf_queue *q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -231,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q);
 int videobuf_mmap_mapper(struct videobuf_queue *q,
                         struct vm_area_struct *vma);
 
-/* --------------------------------------------------------------------- */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+#endif
index 38105031db23b0d89aaf7f838830e3fdab0efb4f..be8da269ee334c0fae41b01dc5def2877f63ed83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * helper functions for PCI DMA video4linux capture buffers
+ * helper functions for SG DMA video4linux capture buffers
  *
  * The functions expect the hardware being able to scatter gatter
  * (i.e. the buffers are not linear in physical memory, but fragmented
@@ -68,9 +68,6 @@ struct videobuf_dmabuf {
        /* for kernel buffers */
        void                *vmalloc;
 
-       /* Stores the userspace pointer to vmalloc area */
-       void                *varea;
-
        /* for overlay buffers (pci-pci dma) */
        dma_addr_t          bus_addr;
 
@@ -81,7 +78,7 @@ struct videobuf_dmabuf {
        int                 direction;
 };
 
-struct videbuf_pci_sg_memory
+struct videobuf_dma_sg_memory
 {
        u32                 magic;
 
@@ -103,11 +100,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
 int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
 struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf);
 
-void *videobuf_pci_alloc (size_t size);
+void *videobuf_sg_alloc(size_t size);
 
-void videobuf_queue_pci_init(struct videobuf_queue* q,
+void videobuf_queue_sg_init(struct videobuf_queue* q,
                         struct videobuf_queue_ops *ops,
-                        void *dev,
+                        struct device *dev,
                         spinlock_t *irqlock,
                         enum v4l2_buf_type type,
                         enum v4l2_field field,
@@ -117,6 +114,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
        /*FIXME: these variants are used only on *-alsa code, where videobuf is
         * used without queue
         */
-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma);
+int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);
 
index 8233cafdeef6de74970ed18f752294e42005c525..b777486963292443ebd9ed9e07b732d34a997ffe 100644 (file)
@@ -27,7 +27,8 @@ struct videobuf_dvb {
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
                          void *adapter_priv,
-                         struct device *device);
+                         struct device *device,
+                         short *adapter_nr);
 void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
 
 /*
index ec63ab0fab93eabc848f3d36690abc5a4c6b77c2..aed39460c154cf73a8d8ecb55fe5edd51dec35b9 100644 (file)
@@ -12,6 +12,8 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2
  */
+#ifndef _VIDEOBUF_VMALLOC_H
+#define _VIDEOBUF_VMALLOC_H
 
 #include <media/videobuf-core.h>
 
@@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
 void *videobuf_to_vmalloc (struct videobuf_buffer *buf);
 
 void videobuf_vmalloc_free (struct videobuf_buffer *buf);
+
+#endif